linux系统是如何通过相同的系统调用函数实现对不同设备进行操作的

        在linux系统中,可以采用open()、read()、write()函数对不同的设备进行访问。比如我们可以用read()来读取一个c文件中的数据,也可以用read()来读取串口发送来的数据。然而c文件和串口的结构显然是不同的,linux是如何通过同一个read()函数来实现不同类型的设备的读取的呢?

       首先我们来看一下linux系统设备访问的机制,我们以最常用的字符设备为例进行分析,字符设备的访问机制如下图所示。

       由图中可以看出我们的应用程序对设备的访问需要通过设备文件来访问。而设备文件又对设备驱动程序进行访问,最后设备驱动程序就直接对硬件设备进行操作了。

       系统调用函数是通过一个重要的结构体来实现驱动函数的映射的,这个结构体是struct file。这个结构体代表一个打开的文件,我们在系统中的每打开的一个文件,在内核空间就会有一个相关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。file结构体中,两个重要的成员如下

loff_t f_pos;
struct file_operations *f_op;

其中loff_t f_pos是文件读写位置,而struct file_operations *f_op;则定义了一些重要函数的,如下面一个实例

struct file_operations fops = {

 .read = device_read,

 .write = device_write,

 .open = device_open,

 .release = device_release

};

在这个结构体中,实际上定义了read(),write()等系统调用函数的映射函数。

       在应用程序中,比如我们打开一个串口的设备文件,则在内核空间中就会生成一个file结构体,以及一个file_operations结构体,当我们对设备进行操作时,内核会到file_operations结构体中查找对应的映射的驱动函数进行相应的操作。

发布了22 篇原创文章 · 获赞 3 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/bhniunan/article/details/104085990