Linux 應用層open調用驅動層open過程


內核版本:3.0.8

open、close、read、write、ioctl等等都是類似。

==========================================================================================

驅動層:

 

struct file_operations fops = 
{
	.open = xxx_open,
	.release = xxx_close,
	.read = xxx_read,
	.write = xxx_write,
	...
};
struct cdev {
	struct module *owner;
	const struct file_operations *ops; //文件操作對象
	struct list_head list; 
	dev_t dev; //設備號
	...
};

 

 

 

// 申請設備號,創建文件操作結構體 struct file_operations fops

static inline int register_chrdev(unsigned int major, const char *name, const struct file_operations *fops);

// 創建字符設備對象結構體 struct cdev,將 fops 賦值給 cdev

struct cdev *cdev;

cdev->ops = fops;

// 將設備號賦值給 cdev, 將 cdev 注冊到鏈表cdev_map

int cdev_add(struct cdev *p, dev_t dev, unsigned count);

p->dev = dev;

kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);

// cdev 結構體中包含 file_operations 和 設備號 dev_t。


// 創建字符設備類

struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key);

// 在類中創建一個設備, /dev 目錄下會生成一個文件,名稱為 led

// 系統自動為此文件分配 inode 節點(linux系統是通過 inode 節點來查找文件),節點中包含此字符設備的設備號 dev_t

struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata,"led");

 

// 每一個文件都有一個inode
struct inode {
	umode_t			i_mode;//就是權限
	uid_t			i_uid; //用戶
	gid_t			i_gid; //用戶組
	dev_t			i_rdev; //設備號
	loff_t			i_size; //大小
	...			...
}

==========================================================================================

應用層:

// 打開驅動中創建的設備,open 會調用VFS層中的 sys_open();

int open("/dev/led", int flags, mode_t mode);

// 調用 sys_open() 的過程,詳見 http://blog.csdn.net/hxmhyp/article/details/22699669 ,感謝這位朋友細心講解

SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode);

==========================================================================================

VFS層:

// open會調用內核中的 sys_open(),這個函數是經過變換得來的,參數與open完全吻合

// 參數1:函數名,

// 參數2:文件名類型

// 參數3:文件名

// 參數4:打開標志類型

// 參數5:打開文件標志

// 參數6:文件權限類型

// 參數7:文件權限

int sys_open(open, const char __user *, filename, int, flags, int, mode)

// 每個文件都對應一個 struct file 結構體,打開一個文件,系統都會將 struct file 添加到 struct fdtable 的數組中

 

struct fdtable {
	unsigned int max_fds;
	struct file __rcu **fd;      /* current fd array */
	fd_set *close_on_exec;
	fd_set *open_fds;
	struct rcu_head rcu;
	struct fdtable *next;
};

 

// 返回的文件描述符就是此文件的 struct file 在數組中的下標,從3開始(stdin-0 stdout-1 stderr-2)

 

struct file {
	struct path		f_path;		// 文件路徑
	const struct file_operations	*f_op;  // 文件操作對象
	unsigned int 		f_flags;	//文件標志
	fmode_t			f_mode;		// 文件權限
	loff_t			f_pos;		// 文件當前偏移量
	void			*private_data;	// 私有數據
	...			...
}

// 通過 struct file 中的文件路徑 f_path 得到文件的 inode 節點

long do_sys_open(int dfd, const char __user *filename, int flags, int mode)

static inline void fsnotify_open(struct file *file)

struct path *path = &file->f_path;

struct inode *inode = path->dentry->d_inode;

// 通過 inode 節點獲取文件設備號

// 遍歷 cdev 鏈表,獲取設備號,與此文件的設備號相同表示匹配成功

// 將匹配成功的 cdev 結構體中的 file_operations 賦值給此文件的 struct file,從而關聯到驅動層中的 xxx_open

==========================================================================================

 

// 應用層	--->   	驅動層
// open		--->	xxx_open
// close	--->	xxx_open
// read		--->	xxx_open
// write	--->	xxx_open


ps:以上的縮進都表示包含於上一個函數中之內。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM