当前位置:Linux教程 - Linux - 内核FAQ(2001.05.16~2001.05.26)

内核FAQ(2001.05.16~2001.05.26)



        

    1、 编译内核出问题
    2、 核心数据:关于防火墙流量统计数据?
    3、 请问解决unresolved symbol 问题的具体操作步骤
    4、 linux网卡驱动程序的问题
    5、 如何得到内核函数的使用手册

    1、编译内核出问题,求救!!

    我编译内核在make bzImage的时候老是出现错误,
    make[2]:***[ksyms.o] Error 1
    make[2]:Leaving directory /usr/src/linux-2.4.4/kernel
    make[1]:***[first_rule]Error 2
    make[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 uve configed modules,dunt forget to:

    #make modules
    #make modules_install

    and
    #make install
    will auto install the new kernel, but ... id 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 /* We e doing kernel work */
    #include /* Specifically, a module */

    /* Deal with CONFIG_MODVERSIONS */
    #if CONFIG_MODVERSIONS==1
    #define MODVERSIONS
    #include
    #endif

    /* For character devices */
    #include /* The character device
    * definitions are here */
    #include /* 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 - 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 /* 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 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 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 theres 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 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 e 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 removed while
    * the file is open by incrementing the usage count
    * (the number of opened references to the module, if
    * its not zero rmmod will fail)
    */
    MOD_INC_USE_COUNT;

    return SUCCESS;
    }


    /* This function is called when a process closes the
    * device file. It doesn have a return value in
    * version 2.0.x because it can fail (you must ALWAYS
    * be able to close a device). In version 2.2.x it is
    * allowed to fail - but we won 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 e now ready for our next caller */
    Device_Open --;

    /* Decrement the usage count, otherwise once you
    * opened the file youll 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 */
    #else
    static 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 write beyond that!) */
    #endif
    {
    /* Number of bytes actually written to the buffer */
    int bytes_read = 0;

    /* If we e 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
    * 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 */
    #else
    static 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 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 ("youll have to create a device file.
    ");
    printk ("We suggest you use:
    ");
    printk ("mknod c %d
    ", 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 theres an error, report it */
    if (ret < 0)
    printk("Error in unregister_chrdev: %d
    ", ret);
    }


    #Makefile是这样写的:

    CC=gcc
    MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX

    chardev.o: chardev.c /usr/include/linux/version.h
    $(CC) $(MODCFLAGS) -c chardev.c


    #insmod时出现错误:

    unresolved symbol __put_user_X

    请问大侠究竟是什么原因

    是没有包含put_user函数所在的库吗?
    还是内核版本问题?

    #Makefile是这样写的:
    CC=gcc
    MODCFLAGS := -Wall -DMODULE -D__KERNEL__ -DLINUX

    chardev.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
    #include
    #include

    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 test
    4 ./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)


    ==>提示信息<==
      欢迎您对此文章发表您的个人意见,在您发表前请您注意以下问题:
      1、您必须是 LinuxAid 的注册用户,而且您已经成功的登录才可以发表,如果您尚未登录,请您点击此处登录,如果您尚未注册,请您点击此处注册,在您登录/注册完成后系统会自动的带您回到本页面;
      2、您所发表的内容权代表您的个人意见,与 LinuxAid 的立场无关,必要时您必须为您所发表的内容负全部责任;
      3、您所发表的内容不允许包含色情、非法或者危害国家安全的言论,否则将依法追究现任;

      在您填写意见相应内容时,请您注意以下问题:
      1、主题最大长度为 120 字节,只允许使用除了“"”、“”之外的中英文字符;
      2、内容最大长度为 250 字节,可以包含任何字符。




    发布人:daming_z 来自:linuxaid