【转】系统调用和驱动程序中相应函数的参数对应关系

应用程序执行open、ioctl等系统调用,它们的参数和驱动程序中相应函数的参数不是一一对应的,其中经过了内核文件系统层的转换。

系统调用函数原型如下:

int open(const char *pathname,int flags)
int ioctl(int d,int request,....)
ssize_t
 read(int fd,void *buf,size_t count)
ssize_t
 write(int fd,const void *buf,size_t count);

int open(const char *pathname,int flags)
int ioctl(int d,int request,....)
ssize_t
 read(int fd,void *buf,size_t count)
ssize_t
 write(int fd,const void *buf,size_t count);

file_operations结构中的成员如下:

int (*open) (struct inode *, struct file *);

int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
int (*open) (struct inode *, struct file *);

可以看到,这些参数有很大一部分是相似的
(1) 系统调用open传入的参数已经被内核文件系统层处理了,在驱动程序中看不出原来的参数了;
(2)系统调用ioclt的参数个数可变,一般最多传入3个:后面两个参数与file_operations结构中ioctl成员的后面两个参数对应;
(3) 系统调用read传入的buf、count参数,对应file_operation结构中read成员的buf、count参数.而参数offp表示用户在文件中进行存取操作的位置,当执行完写操作后由驱动程序设置;
(4)系统调用write与file_operations结构中write成员的参数关系与(3)类似。
 
所有的系统调用(write,read)都是通过统一的“软中断”int80 同内核交互的,当需要使用系统调用时,用户空间的库函数将参数和系统调用号都压入到堆栈,然后执行int80切换到内核执行,内核再根据系统调用号和内核符号表得到对应的内核执行代码,比如write在内核内对应的代码就是sys_write。至于参数,在内核处理过程中会将用户空间的参数转化为内核所表示的形式。你可以看看write的汇编源代码,好像在libc里面,通过ar命令可以提取出来。
 
驱动程序里的write函数有四个参数,函数格式如下: 
short_write (struct inode *inode, struct file *filp, const char *buf, int count) 
而用户程序中的write函数只有三个参数,函数格式如下: 
write(inf fd, char *buf, int count) 
那他们两个是怎么联系在一起的呢?这就要靠操作系统核心中的函数sys_write了,下面 
是Linux Kernel 2.2.14中sys_write中的源代码:
 1 asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count)  
 2 {  
 3     ssize_t ret;  
 4     struct file * file;  
 5     struct inode * inode;  
 6     ssize_t (*write)(struct file *, const char *, size_t, loff_t *); /* 指向驱动程序中的wirte函数的指针*/  
 7 
 8     lock_kernel(); 
 9  
10     ret = -EBADF;  
11     file = fget(fd); /* 通过文件描述符得到文件指针 */  
12     if (!file)  
13         goto bad_file; 
14  
15     if (!(file->f_mode & FMODE_WRITE))  
16         goto out; 
17  
18     inode = file->f_dentry->d_inode; /* 得到inode信息 */  
19     ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, file->f_pos, count);  
20     if (ret)  
21         goto out;  
22     ret = -EINVAL;  
23     if (!file->f_op || !(write = file->f_op->write)) /* 将函数开始时声明的write函数指针指向fops方法中对应的write函数 */  
24         goto out;  
25     down(&inode->i_sem);  
26     ret = write(file, buf, count, &file->f_pos); /* 使用驱动程序中的write函数将数据输入设备,注意看,这里就是四个参数了 */  
27     up(&inode->i_sem);  
28 
29 out:  
30     fput(file);  
31     bad_file:  
32     unlock_kernel();  
33     return ret;  
34 }    

来源

原文地址:https://www.cnblogs.com/skullboyer/p/9287449.html