荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: jjk (Welcome to InstallBBS,Linux!), 信区: Linux
标  题: 内核FAQ4
发信站: 荔园晨风BBS站 (Wed Dec 19 20:22:57 2001), 转信

【 以下文字转载自 jjk 的信箱 】
【 原文由 jjk.bbs@bbs.nju.edu.cn 所发表 】
发信人: altmayer (alt), 信区: LinuxUnix
标  题: 内核FAQ4
发信站: 南京大学小百合站 (Sun Dec 16 06:04:57 2001), 站内信件

【 以下文字转载自 altmayer 的信箱 】
http://LinuxAid.com.cn axing

〖返回〗〖转发〗

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 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 */
#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'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 */
#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'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=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 <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 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开头的
字符串,我还是不知道具体函数的用法,请赐教,谢谢。

    在内核源码理查一下函数实现,不就知道用法了吗 。




--

  puke!
  技工而已

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.239.152]
--
※ 转寄:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: 211.80.41.106]
--
※ 转载:.南京大学小百合站 bbs.nju.edu.cn.[FROM: 211.80.41.106]
--
※ 转寄:.南京大学小百合站 bbs.nju.edu.cn.[FROM: 深圳大学BBS]
--
※ 修改:·jjksam 於 Dec 19 20:27:42 修改本文·[FROM: 192.168.0.146]
※ 转载:·荔园晨风BBS站 bbs.szu.edu.cn·[FROM: 192.168.0.146]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店