主题:《Linux内核模块编程指南》(四)

主题:《Linux内核模块编程指南》(四)
发信人: kevintz()
整理人: kevintz(2000-06-24 00:40:46), 站内信件
《Linux内核模块编程指南》
《Linux Kernel Module Programming Guide》
作者:Ori Pomerantz 中译者:谭志(lkmpg@21cn.com)
  
译者注:
1、LKMPG是一本免费的书,英文版的发行和修改遵从GPL version 2的许可。为了
节省时间,我只翻译了其中的大部分的大意,或者说这只是我学习中的一些中文
笔记吧,不能算是严格上的翻译,但我认为这已经足够了。本文也允许免费发布
,但发布前请和我联系,但不要把本文用于商业目的。鉴于本人的水平,文章中
难免有错误,请大家不吝指正。
2、本文中的例子在Linux(kernel version 2.2.10)上调试通过。你用的Linux必
须支持内核模块的加载,如果不支持,请在编译内核时选上内核模块的支持或升
级你的内核到一个支持内核模块的版本。


                       第四章 /proc文件系统
        
    Linux有一个特别的机制来供内核和内核模块传输信息到用户进程,那就是/
proc文件系统。/proc文件系统本来是为易于访问进程的信息而设计的,也因此而
得名proc,现在大多用于内核显示一些系统信息,例如/proc/modules列出内核中
的模块,/proc/meminfo列出内存的使用统计等等。

    使用/proc文件系统的方式和设备驱动程序的方式很相似:你需要有一个包含
了/proc文件所需的信息的结构体,包括函数指针(本章的例子仅为一个函数,这
个函数将会在尝试读/proc的文件时被调用)。init_module向内核注册这个结构而
cleanup_module则注销它。


    我们使用proc_register_dynamic的原因(译者注:proc_register_dynamic可
能是早期版本提供的函数,这里用proc_register代替,proc_register可以动态
分配i节点号)是我们不需要知道我们所访问的文件的i节点号(inode number),但
要让内核知道i节点号(inode number)以防冲突。普通的文件系统是建立在磁盘上
的,而不是内存里(/proc是建立在内存里的),这种情况下,i节点号是一个指向
磁盘上文件的i节点的位置的一个指针。一个文件的i节点包含了这个文件的信息
,例如文件的权限和文件的数据在磁盘上的位置等等。

    由于无须打开和关闭/proc的文件,所以我们的模块中没有使用两个宏定义:
MOD_INC_USE_COUNT和MOD_DEC_USE_COUNT。因此我们没有方法避免当打开/proc里
的文件时移去内核模块的做法。在下一章,我们会看到一个更难些的,但又更灵
活的可以避免这种问题的实现。
例子procfs.c    


 
/* procfs.c -  create a "file" in /proc 
 * Copyright (C) 1998 by Ori Pomerantz
 * 版权所有 (C) 2000 by Kevin T.Z
 */

/* kevintz注:
 * /usr/include/linux是指向/usr/src/linux/include/linux
 * 的符号连接
 */

/* 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        


/* Necessary because we use the proc fs */
#include <linux/proc_fs.h>


/* 把数据放到proc文件系统的文件里

   参数
   =========
   1. 数据被插入的缓冲区,如果你要使用它的话。
   2. 字符指针的指针。如果你不想使用内核分配的缓冲区的时候用。
   3. 文件的当前位置。
   4. 第一个参数缓冲区的大小。
   5. 零,为以后保留

   使用和返回值
   ======================
   如果你用自己的缓冲区,就将缓冲区的位置放到第二个参数里。
   缓冲区里将是结果,并返回结果的字节数。
   返回值为零表示没有数据(end of file),负数表示出错。
*/
int procfile_read(char *buffer, char **buffer_location, off_t offset, 

                  int buffer_length, int zero)
{
  int len;  /* The number of bytes actually used */

  static char my_buffer[80];  

  static int count = 1;

  /* 我们只给我们的信息一次给用户,如果调用了第二次,则返回0(EOF)
   * 这很重要,因为标准的read调用等到EOF或它的缓冲区被填入数据
   * 才返回 */
  if (offset > 0)
    return 0;

  /* 生成信息并计算长度*/
  len = sprintf(my_buffer, "For the %d%s time, go away!/n", count,
    (count % 100 > 10 && count % 100 < 14) ? "th" :
(count % 10 == 1) ? "st" :
(count % 10 == 2) ? "nd" :
(count % 10 == 3) ? "rd" : "th" );
count++;

/* 保存信息的指针到buffer_localtion*/
*buffer_location = my_buffer;

/* Return the length */
return len;
}


struct proc_dir_entry Our_Proc_File =
{
0, /* Inode number - ignore, it will be filled by
* proc_register_dynamic */
4, /* Length of the file name */
"test", /* The file name */
S_IFREG | S_IRUGO,
/* File mode - this is a regular file which can
* be read by its owner, its group, and everybody*/
1, /* Number of links */
0, 0, /* The uid and gid - we give it to root */
80, /* The size of the file reported by ls. */
NULL,
/* functions which can be done on the inode*/
procfile_read,
/* The read function for this file, the function called
* when somebody tries to read something from it. */
NULL
/* We could have here a function to fill the file's inode, to
* enable us to play with permissions, ownership, etc. */
};


/* Initialize the module - register the proc file */
int init_module()
{
/* kevintz注:proc_root为全局的proc_dir_entry结构体*/
/*return proc_register_dynamic(&proc_root, &Our_Proc_File);*/
/*可能proc_register_dynamic是早期版本所提供的,
我这里找不到,用proc_register代替*/
return proc_register(&proc_root, &Our_Proc_File);
}



/* Cleanup - unregister our file from /proc */
void cleanup_module()
{
proc_unregister(&proc_root, Our_Proc_File.low_ino);
}


编译:
cc -D__KERNEL__ -DLINUX -DMODULE -DDEBUG -O6 -c procfs.c

测试:
当我们insmod procfs后,可以在/proc下看到文件test,用ls -l test可以
看到文件的属性。用cat /proc/test和vi /proc/test都可以读出文件的内容。不
过执行more /proc/test时显示Segmentation fault (core dumped),这应该是m
ore命令的问题。
我们现在设想一下cat /proc/test时发生了什么动作:cat打开文件/proc/t
est并开始读,引发了read系统调用,而/proc/test是proc文件系统的文件,所以
引发了proc文件系统的读动作,这个动作调用了get_info(看后面的结构)所指向
的函数,就是我们的procfile_read函数,proc文件系统把结果返回到用户进程(
cat),cat就显示出了信息。
下一章将给出一个可以读写的proc文件的例子。

译者注:

完整的proc_dir_entry结构体的定义是:

struct proc_dir_entry {
unsigned short low_ino;
unsigned short namelen;
const char *name;
mode_t mode;
nlink_t nlink;
uid_t uid;
gid_t gid;
unsigned long size;
struct inode_operations * ops;
int (*get_info)(char *, char **, off_t, int, int);
void (*fill_inode)(struct inode *, int);
struct proc_dir_entry *next, *parent, *subdir;
void *data;
int (*read_proc)(char *page, char **start, off_t off,
int count, int *eof, void *data);
int (*write_proc)(struct file *file, const char *buffer,
unsigned long count, void *data);
int (*readlink_proc)(struct proc_dir_entry *de, char *page);
unsigned int count; /* use count */
int deleted; /* delete flag */
};

get_info所指的函数是被/usr/src/linux/fs/proc/array.c中很多
实现proc文件系统的函数所调用,以生成给用户的信息。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值