以下是内核提供的几个重要的proc文件系统接口:
(1)read_proc
- int (*read_proc)(char *page, char **start, off_t offset, int count, int *eof, void *data);
read_proc是proc文件输出信息接口,page是将要写入数据的缓冲区指针,start是数据将要写入的页面位置,offset是页面中的偏移量;count是写入的字节数,eof是一个整形数,当没有更多数据时,必须配置这个参数,data是驱动程序特定的数据指针,可用于内部使用。函数的返回值表示实际放入页面缓冲区的数据字节数。
(2)create_proc_entry
- struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,struct proc_dir_entry *parent);
create_proc_entry用来创建proc目录。其中name为文件名称;mode为文件权限;parent为文件的父目录的指针,它为null时代表父目录为/proc。
(3)remove_proc_entry
- void remove_proc_entry(const char *name, struct proc_dir_entry *parent);
remove_proc_entry用于删除上面函数创建的proc条目,参数name给出要删除的proc条目的名称,参数parent指定建立的proc条目所在的目录。
(4)proc_mkdir
- struct proc_dir_entry *proc_mkdir(const char * name, struct proc_dir_entry *parent);
该函数用于创建一个proc目录,参数name用于指定要创建的proc目录的名称,参数parent为该proc目录所在的目录。
在驱动程序中使用proc文件系统,就要了解proc_dir_entry结构:
- struct proc_dir_entry {
- unsigned int low_ino;
- unsigned short namelen;
- const char *name;
- mode_t mode;
- nlink_t nlink;
- uid_t uid; gid_t gid; //进程ID
- loff_t size;
- const struct inode_operations *proc_iops; //结点操作
- const struct file_operations *proc_fops; //文件操作
- get_info_t *get_info;
- struct module *owner; //拥有者
- struct proc_dir_entry *next, *parent, *subdir;
- void *data;
- read_proc_t *read_proc; //读接口
- write_proc_t *write_proc; //写接口
- atomic_t count;/* 引用计数*/
- int pde_users;
- spinlock_t pde_unload_lock;
- struct completion *pde_unload_completion;
- shadow_proc_t *shadow_proc;
- };
例1.9 proc文件系统驱动程序实例
下面的例子演示了如何访问 proc 文件系统。代码见光盘\src\1drivermodel\1-9proc。核心代码如下所示:
- //结点操作
- static struct inode_operations simple_inode_operations = {
- .permission = simple_permission,
- };
- int init_simple_module( void )
- {
- int ret = 0;
- simple_buffer = (char *)vmalloc( MAX_simple_LENGTH );
- if (!simple_buffer)
- {
- ret = -ENOMEM;
- }
- else
- {
- memset( simple_buffer, 0, MAX_LENGTH );
- proc_entry = create_proc_entry( "demo", 0644, NULL );
- if (proc_entry == NULL)
- {
- ret = -ENOMEM;
- vfree(simple_buffer);
- printk(KERN_INFO "demo: Couldn't create proc entry\n");
- }
- else
- {
- proc_entry->proc_iops = &simple_inode_operations;//结点操作
- proc_entry->read_proc = simple_read;
- proc_entry->write_proc = simple_write;
- proc_entry->owner = THIS_MODULE;
- printk(KERN_INFO "demo: Module loaded.\n");
- }
- }
- return ret;
- }
以下是读写操作的框架:
proc文件的操作权限控制代码:
- int simple_read( char *page, char **start, off_t off,int count, int *eof, void *data )
- {
- int size = 0;
- struct task_struct *p;
- char state;
- size+=sprintf(page+size,
- "%5s%7s%7s%7s%7s%7s%7s %s\n\n",
- "PID","UID","PRIO","POLICY",
- "STATE","UTIME","STIME","COMMAND");
- for_each_process(p)
- {
- switch((int)p->state)
- {
- case -1: state='Z'; break;
- case 0: state='R'; break;
- default: state='S'; break;
- }
- size+=sprintf(page+size,
- "%5d%7d%7d%7d%7c%7d%7d %s\n",
- (int)p->pid,
- (int)p->uid,
- (int)p->rt_priority,
- (int)p->policy,
- state,
- (int)p->utime,
- (int)p->stime,
- p->comm);
- }
- return (size);
- }
- ssize_t simple_write( struct file *filp, const char __user *buff,unsigned long len, void *data )
- {
- if(len>MAX_LENGTH)len=MAX_LENGTH;
- if (copy_from_user(simple_buffer, buff, len ))
- {
- return -EFAULT;
- }
- simple_buffer[len] = 0;
- printk(KERN_INFO "simple_write: %s\n",simple_buffer);
- return len;
- }
运行结果如下:
- static int simple_permission(struct inode *inode, int op, struct nameidata *foo)
- {
- printk(KERN_INFO "simple_permission op %d\n",op);
- if(itype==op)
- {
- return -EACCES;
- }
- return 0;
- }
如果将itype配置为34,则屏蔽对/proc/demo的写操作。
- [root@urbetter /home]# insmod demo.ko
- demo: Module loaded.
- [root@urbetter /home]# cat /proc/demo
- simple_permission op 36
- PID UID PRIO POLICY STATE UTIME STIME COMMAND
- 1 0 0 0 S 1 398 init
- 2 0 0 0 S 0 0 kthreadd
- 3 0 0 0 S 0 0 ksoftirqd/0
- 4 0 99 1 S 0 0 watchdog/0
- 5 0 0 0 S 0 0 events/0
- 6 0 0 0 S 0 41 khelper
- 145 0 0 0 S 0 0 kblockd/0
- 156 0 0 0 S 0 0 khubd
- 159 0 0 0 S 0 0 kseriod
- 163 0 0 0 S 0 4 kmmcd
- 187 0 0 0 S 0 0 pdflush
- 188 0 0 0 S 0 0 pdflush
- 189 0 0 0 S 0 0 kswapd0
- 236 0 0 0 S 0 0 aio/0
- 244 0 0 0 S 0 18 nfsiod
- 924 0 0 0 S 0 0 mtdblockd
- 957 0 0 0 S 0 0 kpsmoused
- 1011 0 0 0 S 0 78 rpciod/0
- 1042 0 0 0 S 0 0 syslogd
- 1045 0 0 0 S 1 7 inetd
- 1079 0 0 0 S 707 468 qpe
- 1088 0 0 0 S 2 13 sh
- 1089 0 0 0 S 0 1 init
- 1090 0 0 0 S 0 0 init
- 1091 0 0 0 S 0 2 init
- 1109 0 0 0 S 41 20 qss
- 1110 0 0 0 S 141 42 quicklauncher
- 1118 0 0 0 R 0 2 cat
- [root@urbetter /home]# echo "fgj">/proc/demo
- simple_permission op 34
- simple_write: fgj
- [root@urbetter /home]# insmod demo.ko itype=34
- [root@urbetter /home]# echo "fgj">/proc/demo
- simple_permission op 34
- -/bin/sh: can't create /proc/demo: Permission denied