proc系统文件及编程

1 proc 简介

       1)/proc

              Linux内核提供的一种通过/proc系统文件,可在运行时访问内核内部数据结构、改变内核设置机制。

              Proc是一种伪文件系统,只在内存中存在,不占用外村空间。以文件系统访问形式向外提供接口。 

2)proc_dir_entry 结构             

       structproc_dir_entry {

              ….

       void*data;

       read_proc_t *read_proc;

       write_proc_t *write_proc;

       structlist_head pde_openers; /* who did->open, but not ->release */

};

说明:该结构保存有文件属性等内容,管理proc文件,还有两个读/写函数指针,需要手动设置。其原型为:

       typedef    int (read_proc_t)(char *page, char **start,off_t off,

                       int count, int *eof, void *data);

typedef    int(write_proc_t)(struct file *file, const char __user *buffer,

                        unsigned long count, void *data);


2 proc驱动相关函数

       1)创建目录

              externstruct proc_dir_entry *create_proc_entry(const char *name, mode_t mode,

                                          structproc_dir_entry *parent);      

2)创建文件

              staticinline struct proc_dir_entry *create_proc_read_entry(const char *name,

                                                        mode_tmode, struct proc_dir_entry *base,

                                                        read_proc_t*read_proc, void * data) 

       3)读写文件

       typedef    int(read_proc_t)(char *page, char **start, off_t off,

                       int count, int *eof, void *data);

          page:用户接收数据空间的首地址;

          offset:接收数据空间的相对于首地址的偏移量(单位:字节);

          count:请求读的数据长度

          eof:反馈是否已到所读数据的末尾位置

        data:用户传入的数据

             

typedef    int(write_proc_t)(struct file *file, const char __user *buffer,

                        unsigned long count, void *data);

              file:

                     待写的文件指针

              buffer:

                     用户空间首地址, __user:用户态的地址空间

              count:

                     申请写操作的数据长度

              data:

                     额外的参数传入,扩展用   

 

       4)remove_proc_entry(flag, dir);

              参数:

                     Flag读写权限

                     Dir 为删除的目录

       5)内核态与用户态的数据交换

              不能用用户态的: memcpy, strcpy等

              拷贝到用户空间

              copy_to_user(void__user *to, const void* from, unsigned long n);

              从用户空间读入

              copy_from_user(void*to,void __user *from, unsigned long n);

 

              注:返回值为未被复制的字节数


3 应用实例



static struct proc_dir_entry *prwd_dir=NULL,*prwd_rdonly=NULL,
                            *prwd_rdwr=NULL;
//proc_dir_entry类型用于指代proc文件和proc目录
static char sbufRO[100]="A test string for readonly!\n";
static char sbufRW[100]="";//用于存用户所写数据

static int prwd_rdonly_read(char *page,char **start,off_t offset,int count,int *eof,void *data){
  sprintf(page,"%s",sbufRO); *eof=1; return strlen(sbufRO);
}
//可读可读文件的读服务接口,参数参考上文
static int prwd_rdwr_read(char *page,char **start,off_t offset,int count,int *eof,void *data){
  int len=strlen(sbufRW);
  if(len<=offset){
     printk("No data for reading in sbufRW!\n");
     return 0;//0没有数据可读;-1表示不允许读;>0表示读到的数据总长度
  } 
  if(len-offset<count)count=len-offset;
  memcpy(page+offset,sbufRW+offset,count);
  //offset有值,则表明之前的数据已读,只要eof不为1,系统就会重调调用本读服务接口函数
  //注意要加上offset,不然会覆盖用户接收数据的空间里已接收到的数据
  if(len<=offset+count)*eof=1;
  return offset+count;//总长度
}

static int prwd_rdwr_write(struct file* filep,const char __user *buffer,unsigned long count,void *data){
  unsigned long cnt=count;
  if(cnt>=sizeof(sbufRW))cnt=sizeof(sbufRW)-1;//留一个'\0'空间
  if(copy_from_user(sbufRW,buffer,cnt)){
     printk("Failure to copy all data from user space!\n");
     return -1;
  }
  
  sbufRW[cnt]='\0';
  return cnt;
}
static int __init func_init(void){
   printk(K "Entry %s!\n",__FUNCTION__);
   prwd_dir=proc_mkdir("proc_rw",NULL);
   //创建proc目录,原型:proc_mkdir(待建目录名,上层已存在的目录路径)<--NULL表示默认的"/proc"
   //proc目录不需要专门指写读/写操作函数<--跟普通目录差不多
   if(!prwd_dir){
      printk(K "Can not create dir:/proc/proc_rw!\n");
      goto failure_create_dir;
   }
   printk(K "Success to create dir:/proc/proc_rw!\n");
   
   prwd_rdonly=create_proc_read_entry("rdonly",0400,prwd_dir,prwd_rdonly_read,NULL);
   //创建proc只读文件,原型:create_proc_read_entry(待建文件名,读写权限,上层目录,读服务接口函数名,数据接口<将被读出的数据指针>)
   if(!prwd_rdonly){
      printk(K "Can not create dir:/proc/proc_rw/rdonly!\n");
      goto failure_create_file_rdonly;
   }
   printk(K "Success to create dir:/proc/proc_rw/rdonly!\n");
   
   prwd_rdwr=create_proc_entry("rdwr",0666,prwd_dir);
   //创建可读写的proc文件,原型:create_proc_entry(待建文件名,读写权限,上层目录)
   if(!prwd_rdwr){
      printk(K "Can not create dir:/proc/proc_rw/rdwr!\n");
      goto failure_create_file_rdwr;
   }
   printk(K "Success to create dir:/proc/proc_rw/rdwr!\n");
   prwd_rdwr->read_proc=prwd_rdwr_read;
   prwd_rdwr->write_proc=prwd_rdwr_write;
   //对于create_proc_entry来说,没有专门参数用于绑定读/写服务接口函数<--需要通过所返回的PROC文件对象的read_proc/write_proc函数指针成员来额外绑定
   return 0;//加载成功
failure_create_file_rdwr:    
   remove_proc_entry("rdwr",prwd_dir);
failure_create_file_rdonly:
   remove_proc_entry("rdonly",prwd_dir);  
failure_create_dir:
   remove_proc_entry("proc_rw",NULL);
   //删除proc文件/目录实体,原型:remove_proc_entry(待删文件或目录名,上层目录路径); 
   return -1;//加载失败
}
static void __exit func_exit(void){
   printk(K "Entry %s!\n",__FUNCTION__);
   remove_proc_entry("rdwr",prwd_dir);
   remove_proc_entry("rdonly",prwd_dir);  
   remove_proc_entry("proc_rw",NULL);  
}
module_init(func_init);
module_exit(func_exit);


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值