• [linux驱动]proc学习笔记(一)


    1,在/proc文件系统下创建节点的API
    http://www.cnblogs.com/ziziwu/archive/2011/10/20/2218975.html
      struct proc_dir_entry *create_proc_entry (const char *name, mode_t mode, struct proc_dir_entry *parent);
      其中参数分别是 /proc 文件名,掩码,父目录。

    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1. 32 struct proc_dir_entry {  
    2. 33         unsigned int low_ino;  
    3. 34         umode_t mode;  
    4. 35         nlink_t nlink;  
    5. 36         kuid_t uid;  
    6. 37         kgid_t gid;  
    7. 38         loff_t size;  
    8. 39         const struct inode_operations *proc_iops;  
    9. 40         const struct file_operations *proc_fops;  
    10. 41         struct proc_dir_entry *next, *parent, *subdir;  
    11. 42         void *data;  
    12. 43         atomic_t count;         /* use count */  
    13. 44         atomic_t in_use;        /* number of callers into module in progress; */  
    14. 45                         /* negative -> it's going away RSN */  
    15. 46         struct completion *pde_unload_completion;  
    16. 47         struct list_head pde_openers;   /* who did ->open, but not ->release */  
    17. 48         spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */  
    18. 49         u8 namelen;  
    19. 50         char name[];  
    20. 51 };  
    [cpp] view plaincopy在CODE上查看代码片派生到我的代码片
     
    1.    
    2. 2,实现read和write proc文件系统节点的函数,分别为read_proc和write_proc函数  
    3.  原型函数:int (*read_proc)(char *page, char **start, off_t offset, int count, int *eof, void *data)  
    4.  原型函数:typedef int (write_proc_t)(struct file *file, const char __user *buffer, unsigned long count, void *data);  

     http://blog.csdn.net/wbd880419/article/details/6637102
      对于read_proc_t
     
    1. 第一个参数:为啥叫page?答案就是如果对proc文件调用读操作,内核会分配一个页大小的缓冲区。如何输出大于一个页的数据呢,这得依赖于第二个和第三个参数了。
    为了理解第二三个参数,回忆下与文件操作相关的系统调用:
    int open(const char *pathname, int flags);
    off_t lseek(int fildes, off_t offset, int whence);
    ssize_t read(int fd, void *buf, size_t count);
    ssize_t write(int fd, const void *buf, size_t count);
    对于proc文件,一次read操作最多只能读取一个page的数据,如果需要读取大于一个页的数据需要保存read的返回值,
    然后使用lseek设定offset,然后再次调用read。回到参数的说明:
    2. start和off参数:off对应于lseek里面的offset(lseek whence为SEEK_END,offset为负 的情况下,传进来的off为零,具体原因待考古)。
    如果不设置*start的值,off的取值只能在[0, count - 1]之间,且能够读取的数据大小为:count - off。可以理解系统拷贝了
     [page + off, page+count - 1]之间的数据到用户的buffer里。如果off的取值超出范围,read将读不到数据。
    如果设置了*start的值,系统认为*start指向的地址就是off指定的地址,off的值会被忽略,系统会拷贝[start, start+count-1]之间的
    数据到用户空间。当然我们在实现start地址的定位时,可能会需要off的值。
    3. count 参数与read中的count一致
    4. eof参数,设置了这个参数表明不想再提供数据了,神马意思呢?
    如果不设置这个参数,对于上面说的start为空的情况,read_proc返回后,系统如果发现 (count - off) < count 
    会接着下发写请求,读取off大小的数据。
    例如:有这样的读取操作:
    lseek(fd, 2, SEEK_SET); read(fd, buff_r, 30)
    第一次调用read_proc, off=2, count=30, 由于我们没有设置start的值,将读取28字节的数据,由于没有设置*eof, 系统会再次下发read_proc
    第二次调用read_proc, off=30, count=2, 在参数start的说明里提到,对于这个调用,系统默认读不到数据(怨念啊,为啥要下发)
    于是read返回28
    如果设置了这个参数就不会有第二次的下发了。
    5. data参数,这个是给驱动程序预留的参数。
    对于write_proc函数,参数是很简单的,需要说明的只有一点,就是write_proc的第二个参数buffer是用户态的地址,需要用copy_from_user
    从用户态把数据拷到内核态的缓冲区里。

  • 相关阅读:
    neo4j 图数据库
    eclipse 当中,两种添加插件的方法 .
    ubuntu16.04如何添加用root用户登录图形界面
    遇到Linux系统安装时窗口过大,按钮点不到,该怎么解决
    hadoop 搭建3节点集群,遇到Live Nodes显示为0时解决办法
    VMware 虚拟机克隆 CentOS 6.5 之后,网络配置问题的解决方案
    scala(13)-----集合(Collection)-------元组
    scala(13)-----集合(Collection)-------Map(映射)
    scala(13)-----集合(Collection)-------Set(集合)
    scala(13)-----集合(Collection)-------列表
  • 原文地址:https://www.cnblogs.com/zhiliao112/p/4237224.html
Copyright © 2020-2023  润新知