内核FAQ 3 (2001.05.16~2001.05.26)

    技术2022-05-11  46

    内核FAQ(2001.05.16~2001.05.26)

    http://LinuxAid.com.cn axing〖返回〗〖转发〗

    1、 编译内核出问题2、 核心数据:关于防火墙流量统计数据?3、 请问解决unresolved symbol 问题的具体操作步骤4、 linux网卡驱动程序的问题5、 如何得到内核函数的使用手册1、编译内核出问题,求救!! 我编译内核在make bzImage的时候老是出现错误,make[2]:***[ksyms.o] Error 1make[2]:Leaving directory '/usr/src/linux-2.4.4/kernel'make[1]:***[first_rule]Error 2make[1]:Leaving directory '/usr/src/linux-2.4.4/kernel'make:***[_dir_kernel] Error 2这些表示什么意思?怎么看?    还有,编译的时候说有好些变量没declared(比如说,smp_num_cpus,在/usr/src/linux-2.4.4/include/linux/kernel_stat.h)中,可是我查了它是给定义了啊,这是怎么回事?多谢各位指点 #Try this simple way:#make mrproper   /* clean old config info */#make clean      /* clean old object file */#make menuconfig /* do nothing,just exit and save config,all use default */#make dep        /* binding the configuration info */#make bzImage    /* it should work. */#cp arch/i386/boot/bzImage /boot/bzImage_00#vi /etc/lilo.conf /* add the new bzImage_00 to lilo */#lilo#reboot    高,实在是高!真可以了.为什么会这样?前面两条命令起了什么作用?请高手指点.    你好,我第一次编译内核时,只注意了声卡支持,其他的按系统默认,编译顺利通过,重新引导也一切正常。在mount一个Fat16分区时,发现fs vfat can not be supported。我怀疑编译内核时MSDOS和VFAT是不是没有选上,就重新编译内核,特别的注意了这两个选项,其他照旧,结果make dep; make clean; make zImage都通过了,make modules时出了问题:*** [dummy.o] error 1*** [modsubdir_net] error 2*** [mod_drivers] error 2    我该怎么办呢?如果说内核源码有问题,我第一次编译怎么没有出错呢。    我的内核版本:kernel-2.4.2-2    源码:kernel-source-2.4.2-2          kernel-headers-2.4.2-2        if u've configed modules,dunt forget to:#make modules#make modules_install    and #make install    will auto install the new kernel, but ... i'd rather install it by myself.2、核心数据:关于防火墙流量统计数据?     在核心2.0时,有/proc/net/ip_acct文件用于存放防火墙流量统计数据;在核心2.2时,没有了此文件。只有/proc/net/ip_fwchains和 /proc/net/ip_fwnames 文件。请问,我如何访问以前的ip_acct文件中的数据呢?有相关的或是相对应的文件吗?它们的格式是什么?    你可以通过firewall library来访问每一条规则的流量统计信息。 3、请问解决unresolved symbol 问题的具体操作步骤#以下是一个字符设备驱动程序例子的源代码:/* chardev.c  * Copyright (C) 1998-1999 by Ori Pomerantz *  * Create a character device (read only) *//* The necessary header files *//* Standard in kernel modules */#include <linux/kernel.h>   /* We're doing kernel work */#include <linux/module.h>   /* Specifically, a module *//* Deal with CONFIG_MODVERSIONS */#if CONFIG_MODVERSIONS==1#define MODVERSIONS#include <linux/modversions.h>#endif        /* For character devices */#include <linux/fs.h>       /* The character device                              * definitions are here */#include <linux/wrapper.h>  /* A wrapper which does                              * next to nothing at                             * at present, but may                              * help for compatibility                             * with future versions                              * of Linux *//* In 2.2.3 /usr/include/linux/version.h includes  * a macro for this, but 2.0.35 doesn't - so I add  * it here if necessary. */#ifndef KERNEL_VERSION#define KERNEL_VERSION(a,b,c) ((a)*65536+(b)*256+(c))#endif/* Conditional compilation. LINUX_VERSION_CODE is  * the code (as per KERNEL_VERSION) of this version. */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,2,0)#include <asm/uaccess.h>  /* for put_user */#endif     #define SUCCESS 0/* Device Declarations **************************** *//* The name for our device, as it will appear  * in /proc/devices */#define DEVICE_NAME "char_dev"/* The maximum length of the message from the device */#define BUF_LEN 80/* Is the device open right now? Used to prevent  * concurent access into the same device */static int Device_Open = 0;/* The message the device will give when asked */static char Message[BUF_LEN];/* How far did the process reading the message  * get? Useful if the message is larger than the size  * of the buffer we get to fill in device_read. */static char *Message_Ptr;/* This function is called whenever a process  * attempts to open the device file */static int device_open(struct inode *inode,        struct file *file){  static int counter = 0;#ifdef DEBUG  printk ("device_open(%p,%p)", inode, file);#endif  /* This is how you get the minor device number in    * case you have more than one physical device using    * the driver. */  printk("Device: %d.%d",  inode->i_rdev >> 8, inode->i_rdev & 0xFF);  /* We don't want to talk to two processes at the    * same time */  if (Device_Open)    return -EBUSY;  /* If this was a process, we would have had to be    * more careful here.   *   * In the case of processes, the danger would be    * that one process might have check Device_Open    * and then be replaced by the schedualer by another    * process which runs this function. Then, when the    * first process was back on the CPU, it would assume    * the device is still not open.    *   * However, Linux guarantees that a process won't be    * replaced while it is running in kernel context.    *   * In the case of SMP, one CPU might increment    * Device_Open while another CPU is here, right after    * the check. However, in version 2.0 of the    * kernel this is not a problem because there's a lock    * to guarantee only one CPU will be kernel module at    * the same time. This is bad in  terms of    * performance, so version 2.2 changed it.    * Unfortunately, I don't have access to an SMP box    * to check how it works with SMP.   */  Device_Open++;  /* Initialize the message. */  sprintf(Message,     "If I told you once, I told you %d times - %s",    counter++,    "Hello, world");  /* The only reason we're allowed to do this sprintf    * is because the maximum length of the message    * (assuming 32 bit integers - up to 10 digits   * with the minus sign) is less than BUF_LEN, which    * is 80. BE CAREFUL NOT TO OVERFLOW BUFFERS,    * ESPECIALLY IN THE KERNEL!!!    */   Message_Ptr = Message;  /* Make sure that the module isn't removed while    * the file is open by incrementing the usage count    * (the number of opened references to the module, if    * it's not zero rmmod will fail)   */  MOD_INC_USE_COUNT;  return SUCCESS;}/* This function is called when a process closes the  * device file. It doesn't have a return value in  * version 2.0.x because it can't fail (you must ALWAYS * be able to close a device). In version 2.2.x it is  * allowed to fail - but we won't let it.  */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)static int device_release(struct inode *inode,   struct file *file)#else static void device_release(struct inode *inode,    struct file *file)#endif{#ifdef DEBUG  printk ("device_release(%p,%p)", inode, file);#endif   /* We're now ready for our next caller */  Device_Open --;  /* Decrement the usage count, otherwise once you    * opened the file you'll never get rid of the module.   */  MOD_DEC_USE_COUNT;#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  return 0;#endif}/* This function is called whenever a process which  * have already opened the device file attempts to  * read from it. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)static ssize_t device_read(struct file *file,    char *buffer,    /* The buffer to fill with data */    size_t length,   /* The length of the buffer */    loff_t *offset)  /* Our offset in the file */#elsestatic int device_read(struct inode *inode,                       struct file *file,    char *buffer,   /* The buffer to fill with      * the data */     int length)     /* The length of the buffer                      * (mustn't write beyond that!) */#endif{  /* Number of bytes actually written to the buffer */  int bytes_read = 0;  /* If we're at the end of the message, return 0    * (which signifies end of file) */  if (*Message_Ptr == 0)    return 0;  /* Actually put the data into the buffer */  while (length && *Message_Ptr)  {    /* Because the buffer is in the user data segment,      * not the kernel data segment, assignment wouldn't      * work. Instead, we have to use put_user which      * copies data from the kernel data segment to the      * user data segment. */    put_user(*(Message_Ptr++), buffer++);    length --;    bytes_read ++;  }#ifdef DEBUG   printk ("Read %d bytes, %d left",     bytes_read, length);#endif   /* Read functions are supposed to return the number     * of bytes actually inserted into the buffer */  return bytes_read;}/* This function is called when somebody tries to write  * into our device file - unsupported in this example. */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)static ssize_t device_write(struct file *file,    const char *buffer,    /* The buffer */    size_t length,   /* The length of the buffer */    loff_t *offset)  /* Our offset in the file */#elsestatic int device_write(struct inode *inode,                        struct file *file,                        const char *buffer,                        int length)#endif{  return -EINVAL;}/* Module Declarations ***************************** *//* The major device number for the device. This is  * global (well, static, which in this context is global * within this file) because it has to be accessible  * both for registration and for release. */static int Major;/* This structure will hold the functions to be  * called when a process does something to the device  * we created. Since a pointer to this structure is  * kept in the devices table, it can't be local to * init_module. NULL is for unimplemented functions. */struct file_operations Fops = {  NULL,   /* seek */  device_read,   device_write,  NULL,   /* readdir */  NULL,   /* select */  NULL,   /* ioctl */  NULL,   /* mmap */  device_open,#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,0)  NULL,   /* flush */#endif  device_release  /* a.k.a. close */};/* Initialize the module - Register the character device */int init_module(){  /* Register the character device (atleast try) */  Major = module_register_chrdev(0,                                  DEVICE_NAME,                                 &Fops);  /* Negative values signify an error */  if (Major < 0) {    printk ("%s device failed with %d",    "Sorry, registering the character",    Major);    return Major;  }  printk ("%s The major device number is %d.",          "Registeration is a success.",          Major);  printk ("If you want to talk to the device driver,");  printk ("you'll have to create a device file. ");  printk ("We suggest you use:");  printk ("mknod <name> c %d <minor>", Major);  printk ("You can try different minor numbers %s",          "and see what happens.");  return 0;}/* Cleanup - unregister the appropriate file from /proc */void cleanup_module(){  int ret;  /* Unregister the device */  ret = module_unregister_chrdev(Major, DEVICE_NAME);   /* If there's an error, report it */   if (ret < 0)    printk("Error in unregister_chrdev: %d", ret);}#Makefile是这样写的:CC=gccMODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUXchardev.o: chardev.c /usr/include/linux/version.h$(CC) $(MODCFLAGS) -c chardev.c#insmod时出现错误:unresolved symbol __put_user_X 请问大侠究竟是什么原因是没有包含put_user函数所在的库吗?还是内核版本问题?#Makefile是这样写的:CC=gccMODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUXchardev.o: chardev.c /usr/include/linux/version.h$(CC) $(MODCFLAGS) -c chardev.c编译时加“O”参数$(CC) -O $(MODCFLAGS) -c chardev.c这是由于内核编程会用到很多内联函数(inline),需要此参数为什么内联函数需要-O选项  内联函数需在编译期间被编译器整块拷贝到目标文件,就象处理宏一样 编译通过了, insmod也没有问题, 我测试了一下, 出了问题。我的操作步骤(用的都是root):1 mknod /dev/mychar c 254 0  /*insmod时主设备号为254*/2 test.c#include <stdio.h>#include <fcntl.h>#include <unistd.h>int main(){   int fd;   char buf[80];   fd = open("mychar", O_RDONLY, 0);   if(fd == -1)      printf("error: open mychar");   else   {       if(read(fd, buf, 80) == -1)           printf("read error!");       else           printf("the read result is : %s", buf);    }}3 gcc test.c -o test4 ./test提示: error: open mychar 请问斑竹, 这是为何? 文件路径错:改为:mknod mychar c 254 0或者:fd=open("/dev/mychar",O_RDWR);4、linux网卡驱动程序的问题    我编了一个linux网卡驱动程序,我的网卡是NE2000的,其实我并没有使用NE2000的资料,因为我不知道,我只把网卡设为IRQ=3, I/O=OX300,编译通过,PING 自己可以,但PING 别人就不行了,甚至马上重启机器,问扎回事?      在用户模式下,进程访问到无效内存地枝是(一般是数组越界)一般是将进程的内存映射写成名为core 的文件,然后退出,而在内核模式下linux就无能为力啦,只好马上重起,linux 源带码中有ne2000的驱动源代码(/usr/src/linux/drivers/net/ne2k-pci.c),你可参考一下。5、如何得到内核函数的使用手册    编驱动程序时,常回用到比如“printk,kfree,request_irq...."等等一系列内核函数,用man又不行,请问该怎么拌,谢谢!      /proc/kysms中既是      实在是对不起,我已看了kysms文件,里面只有函数名,后面跟一串以R开头的字符串,我还是不知道具体函数的用法,请赐教,谢谢。         在内核源码理查一下函数实现,不就知道用法了吗 。

    责任编辑:axing(2001-06-06 17:24)

    最新回复(0)