rss· 投稿· 设为首页· 加入收藏· 繁體版
当前位置: 火魔网 » 操作系统 » Linux基础

linux驱动开发之proc

1、首先认识一下procfs文件系统本身,其最初设计的目的是允许更方便的对进程信息进行访问(因此得名),现在的proc则包含了更多的内容,进程相关部分,系统信息部分,以及系统子系统部分。 2、linux驱动开发过程中,可以通过两种方式在/proc中注册文件,一种在linux/proc_fs.h中进行定义,接口
十分简单易用,主要包括四个函数接口:
create_proc_entryproc_mkdir
remove_proc_entry

4.3.1. Using the /proc Filesystem 4.3.1. 使用/proc文件系统 The /proc filesystem is a special, software-created filesystem that is used by the kernel to export information to the world. Each file under /proc is tied to a kernel function that generates the file's "contents" on the fly when the file is read. We have already seen some of these files in action; /proc/modules, for example, always returns a list of the currently loaded modules. /proc文件系统是一个特殊的,由软件创建的文件系统,内核使用此文件系统来向外部输出信息。/proc目录下的每一个文件都与内核函数紧密相连,当文件被读取时内核函数轻松地生成文件的“内容”。我们前面已经了解过其中的一些文件;例如/proc/modules文件,始终会返回当前加载的模块列表。 /proc is heavily used in the Linux system. Many utilities on a modern Linux distribution, such as ps, top, and uptime, get their information from /proc. Some device drivers also export information via /proc, and yours can do so as well. The /proc filesystem is dynamic, so your module can add or remove entries at any time. /proc在Linux系统中被广泛的应用。在目前的Linux发行版中,有许多命令像ps,top及uptime,都是通过/proc获取它们所需的信息。许多设备驱动程序也会通过/proc向外界输出信息,当然你的驱动程序也可以这样做。/proc文件系统是动态的,因此你的模块可以随时在其中添加或删除条目。 Fully featured /proc entries can be complicated beasts; among other things, they can be written to as well as read from. Most of the time, however, /proc entries are read-only files. This section concerns itself with the simple read-only case. Those who are interested in implementing something more complicated can look here for the basics; the kernel source may then be consulted for the full picture. 想要完全了解/proc条目的所有功能是非常困难的;此外,它们还支持写操作。然而,在大多数情况下,/proc条目是只读的。这一节讨论的话题只涉及简单的只读情况。想深入研究/proc的读者可以把这一节当作是一个基础;然后分析内核源码也许是学习它的最佳途径。 Before we continue, however, we should mention that adding files under /proc is discouraged. The /proc filesystem is seen by the kernel developers as a bit of an uncontrolled mess that has gone far beyond its original purpose (which was to provide information about the processes running in the system). The recommended way of making information available in new code is via sysfs. As suggested, working with sysfs requires an understanding of the Linux device model, however, and we do not get to that until Chapter 14. Meanwhile, files under /proc are slightly easier to create, and they are entirely suitable for debugging purposes, so we cover them here. 然而,在我们讨论之前,我们应该先声明,在/proc下添加文件是不明智的。内核开发者把/proc文件系统看作一个自由自在的大杂烩,这大大超出了它原来的目的(提供运行在系统中的进程信息)。因此推荐的做法是通过sysfs来输出信息。然而,与sysfs协同工作需要对linux的设备模型有深刻的了解,我们要到第14章才会谈论这个话题。因此在这期间,创建/proc下的文件还是较为简单的,并且它们完全能够达到调试目的,所以下面我们就来看看它们。

4.3.1.1 Implementing files in /proc 4.3.1.1 创建/proc文件 All modules that work with /proc should include <linux/proc_fs.h> to define the proper functions. 所有使用/proc的模块都应该包含<linux/proc_fs.h>头文件来定义相应的函数。 To create a read-only /proc file, your driver must implement a function to produce the data when the file is read. When some process reads the file (using the read system call), the request reaches your module by means of this function. We'll look at this function first and get to the registration interface later in this section. 为了创建只读的/proc文件,你的驱动程序必须实现一个函数,当文件被读取时此函数可以产生文件数据。当某些进程读取文件时(使用read系统调用),这个读取请求会通过该函数传达到你的模块中。我们会先粗略浏览一下这个函数,我们首先来看看这个函数然后再讨论有关的注册接口。 When a process reads from your /proc file, the kernel allocates a page of memory (i.e., PAGE_SIZE bytes) where the driver can write data to be returned to user space. That buffer is passed to your function, which is a method called read_proc: 当一个进程读取你的/proc文件时,内核就会为你的驱动程序分配一页的内存(例如,PAGE_SIZE字长),驱动程序会把数据写入这块内存从而把数据传递给用户空间。这个缓冲区的地址通过函数read_proc传递给你的函数: int (*read_proc)(char *page, char **start, off_t offset, int count, int *eof, void *data);

The page pointer is the buffer where you'll write your data; start is used by the function to say where the interesting data has been written in page (more on this later); offset and count have the same meaning as for the read method. The eof argument points to an integer that must be set by the driver to signal that it has no more data to return, while data is a driver-specific data pointer you can use for internal bookkeeping. 其中,page指针就指向你将写入数据的缓冲区;start参数是在此缓冲区内数据的起始位置(稍后我们再详细讨论);参数offset和count的意义与read函数中的一样。参数eof指向一个整型数值,当没有返回数据时驱动程序必须通过设置该数值向用户空间发出通知,参数data是驱动程序自定义的数据指针,可以用作内部日志。 This function should return the number of bytes of data actually placed in the page buffer, just like the read method does for other files. Other output values are *eof and *start. eof is a simple flag, but the use of the start value is somewhat more complicated; its purpose is to help with the implementation of large (greater than one page) /proc files. 这个函数应该返回放置在page缓冲区内的实际字节数,对其他文件来说,这仅仅像是一个read函数。其他的输出数值是*eof和*start。eof是一个简单的标志,但是start参数的用法稍微有些复杂;它的作用是帮助创建大型的(大于一页的)/proc文件。 The start parameter has a somewhat unconventional use. Its purpose is to indicate where (within page) the data to be returned to the user is found. When your proc_read method is called, *start will be NULL. If you leave it NULL, the kernel assumes that the data has been put into page as if offset were 0; in other words, it assumes a simple-minded version of proc_read, which places the entire contents of the virtual file in page without paying attention to the offset parameter. If, instead, you set *start to a non-NULL value, the kernel assumes that the data pointed to by *start takes offset into account and is ready to be returned directly to the user. In general, simple proc_read methods that return tiny amounts of data just ignore start. More complex methods set *start to page and only place data beginning at the requested offset there.  start参数的用法有些特别。它的目的是在page指向的缓冲区中指明返回到用户空间的数据的起始位置。当proc_read函数被调用时,*start将会初始化为NULL。如果你不给它赋值,内核就会认为数据已经写入page指向的缓冲区,就好像offset参数为0一样;也就是说,内核会认为这个愚蠢的proc_read函数并不关心offset参数而是直接放置整个虚拟文件的内容。相反,如果你为*start指定一个非NULL值,那么那么内核就会认为*start指向的数据是依照offset参数放置的,并准备把这些数据直接传递给使用者。通常情况下,简单的proc_read函数仅返回很少的数据,因此会忽略start。而更复杂的函数会设置page缓冲区中*start的位置并把数据放置在所请求偏移量的起始处。 There has long been another major issue with /proc files, which start is meant to solve as well. Sometimes the ASCII representation of kernel data structures changes between successive calls to read, so the reader process could find inconsistent data from one call to the next. If *start is set to a small integer value, the caller uses it to increment filp->f_pos independently of the amount of data you return, thus making f_pos an internal record number of your read_proc procedure. If, for example, your read_proc function is returning information from a big array of structures, and five of those structures were returned in the first call, *start could be set to 5. The next call provides that same value as the offset; the driver then knows to start returning data from the sixth structure in the array. This is acknowledged as a "hack" by its authors and can be seen in fs/proc/generic.c.  /proc文件还有另外一种有关start用法的重要情况。有时内核数据结构的ASCII表现体在read函数不同的继承调用中会有所改变,所以执行读取操作的进程就有可能会读到不一致的数据。如果*start被设置为一个较小的整数,那么调用进程就会利用它来增加filp->f_pos的值而不必依据你所返回的数据量。你的read_proc函数要从一个较大的结构体数组中返回信息,第一次调用返回了五个结构体,*start会被设置为5。在下一次调用时就会将改值作为偏移量;然后驱动程序就会知道要从数组的第六结构体中返回数据。这是一个公认的“hack”技巧并且可以在fs/proc/generic.c中查看其相关信息。

顶一下
(0)
踩一下
(0)