系統調用和驅動程序中相應函數的參數對應關係

轉自:http://blog.sina.com.cn/s/blog_6405313801012p9r.html

 

應用程序執行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中的源代碼:
asmlinkage ssize_t sys_write(unsigned int fd, const char * buf, size_t count)
{
ssize_t ret;
struct file * file;
struct inode * inode;
ssize_t (*write)(struct file *, const char *, size_t, loff_t *); 

lock_kernel();
ret = -EBADF;
file = fget(fd); 
if (!file)
goto bad_file;
if (!(file->f_mode & FMODE_WRITE))
goto out;
inode = file->f_dentry->d_inode; 
ret = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file, file->f_pos,
count);
if (ret)
goto out;
ret = -EINVAL;
if (!file->f_op || !(write = file->f_op->write)) 
goto out;
down(&inode->i_sem);
ret = write(file, buf, count, &file->f_pos); 
up(&inode->i_sem);
out:
fput(file);
bad_file:
unlock_kernel();
return ret;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章