内核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) |