open系统调用、syscall_open函数和drv_open函数之间的联系和区别
-
open系统调用:-
角色:用户空间的系统调用接口,用于打开文件或设备。
-
作用:这是用户程序用来请求打开文件的接口。用户程序通过调用
open系统调用(如open("/dev/mydevice", O_RDWR))来打开文件或设备,获取一个文件描述符。 -
实现:
open系统调用在用户空间的C标准库(如glibc)中实现,会触发内核中的相应处理函数陷入内核空间,最终调用具体的文件或设备驱动程序的open实现。 -
示例:
int fd = open("/dev/my_device", O_RDWR);
-
-
syscall_open函数:-
角色:位于内核空间,是内核中的系统调用处理函数,是
open系统调用在内核中的实现。 -
作用:
syscall_open是内核处理open系统调用的入口点。它负责解析用户空间传入的参数(如文件路径、打开标志等),并调用与文件或设备关联的file_operations结构体中具体的驱动程序的open方法,即drv_open来打开文件。 -
实现:
syscall_open通常由内核开发者实现,是内核的一个内部函数。 -
示例:
// 内核中系统调用处理函数的简化示例 long sys_open(const char __user *filename, int flags, umode_t mode) { // 查找文件路径,获取 inode 和 file 结构体 struct file *filp = do_filp_open(AT_FDCWD, filename, flags); // 调用文件的 open 方法 return finish_open(filp, NULL, O_RDWR);c }
-
-
drv_open函数:-
角色:
drv_open位于具体的设备驱动程序代码中,是设备驱动程序中的具体实现函数,是file_operations结构体中的一个函数指针。 -
作用:
drv_open是具体设备驱动程序实现的open方法。它执行与设备打开相关的具体操作,如初始化设备、分配资源等。 -
实现:
drv_open由设备驱动开发者实现,作为file_operations结构体中的open方法,主要功能是执行设备特定的操作,如初始化硬件、分配设备资源、设置设备状态等。 -
示例:
// 设备驱动程序中的 open 方法实现 static int drv_open(struct inode *inode, struct file *filp) { // 设备特定的初始化操作 printk(KERN_INFO "Device opened\n"); return 0; } static const struct file_operations my_fops = { .owner = THIS_MODULE, .open = drv_open, // 其他操作函数 };
-
之间的联系和流程
-
用户空间调用
open系统调用:-
用户空间的应用程序通过调用
open系统调用请求打开一个文件或设备。
-
-
进入内核空间,调用
syscall_open:-
系统调用机制将控制权转交给内核,进入
syscall_open函数(具体名称和实现可能因内核版本不同而有所不同)。
-
-
内核找到对应的文件系统操作方法:
-
syscall_open通过文件路径找到对应的inode结构体,从而找到与该文件或设备相关的struct file_operations结构体。
-
-
调用驱动程序的
open方法(drv_open):-
内核通过
file_operations结构体中的open方法指针,调用具体驱动程序实现的drv_open函数。 -
drv_open执行设备特定的打开操作,如硬件初始化、资源分配等。
-
函数实现的伪代码
syscall_open函数实现的伪代码:
int syscall_open(const char *filename,int flag)
{
dev_t devno;
struct inode *pnode = NULL;
struct cdev *pcdev = NULL;
struct file *pfile = NULL;
int fd = -1;
/*根据filename在内核中查找该文件对应的struct inode对象地址
找到则pnode指向该对象
未找到则创建新的struct inode对象,pnode指向该对象,并从文件系统中读取文件的元信息到该对象*/
if(/*未找到对应的struct inode对象*/)
{/*根据文件种类决定如何进行下面的操作,如果是字符设备则执行如下操作*/
/*从pnode指向对象中得到设备号*/
devno = pnode->i_rdev;
/*用devno在字符设备链表查找对应节点,并将该节点的地址赋值给pcdev*/
/*pcdev赋值给pnode的i_cdev成员*/
pnode->i_cdev = pcdev;
}
/*创建struct file对象,并将该对象的地址赋值给pfile*/
pfile->f_op = pnode->i_cdev->ops;
pfile->f_flags = flag;
/*调用驱动程序的open函数*/
pfile->f_op->open(pnode,pfile,flag);
/*将struct file对象地址填入进程的描述符数组,得到对应位置的下标赋值给fd*/
return fd;
}
5万+

被折叠的 条评论
为什么被折叠?



