日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Linux系统中,read文件过程分析

發布時間:2025/3/15 linux 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统中,read文件过程分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
read一個文件 首先是通過系統調用open一個文件 大家好,我是ChinaUnix的T-bagwell 然后通過系統調用去read一個文件,為什么man 2 read的時候或者man 2 write的時候的參數與寫的驅動的read和write里面定義的函數看上去不同呢?

ssize_t?read(int?fd,?void?*buf,?size_t?count);
ssize_t?
write(int?fd,?const?void?*buf,?size_t?count);

下面是driver/nvram.c里面的

static?ssize_t nvram_read(struct?file?*file,?char?__user?*buf,?size_t?count,?loff_t?*ppos)
static?ssize_t nvram_write(struct?file?*file,?const?char?__user?*buf,?size_t?count,?loff_t?*ppos)


下面就以說read為例就可以了

391 SYSCALL_DEFINE3(read,?unsigned?int,?fd,?char?__user?*,?buf,?size_t,?count)
392?{
393?struct?file?*file;
394 ssize_t ret?=?-EBADF;
395?int?fput_needed;
396
397?file?=?fget_light(fd,?&fput_needed);
398?if?(file)?{
399 loff_t pos?=?file_pos_read(file);
400 ret?=?vfs_read(file,?buf,?count,?&pos);
401 file_pos_write(file,?pos);
402 fput_light(file,?fput_needed);
403?}
404
405?return?ret;
406?}

通過閱讀代碼,發現這個系統調用read與man看到的系統調用的定義的是相同的,沒有這里可以沒有疑問,但是這個比nvram.有些不同,其實操作都是在這個系統調用里面,struct?
file *file結構里面的file是通過這個fget_light來或得到的,這個file結構如下:

918?struct?file?{
?919?
/*
?920 * fu_list becomes invalid after file_free is called and queued via
?921 * fu_rcuhead for RCU freeing
?922 */

?923?
union?{
?924?
struct?list_head fu_list;
?925?
struct?rcu_head fu_rcuhead;
?926?
}?f_u;
?927?
struct?path f_path;
?928?
#define?f_dentry f_path.dentry
?929?
#define?f_vfsmnt f_path.mnt
?930?
const?struct?file_operations?*f_op;
?931 spinlock_t f_lock
;?/* f_ep_links, f_flags, no IRQ */
?932 atomic_long_t f_count
;
?933?
unsigned?int?f_flags;
?934 fmode_t f_mode
;
?935 loff_t f_pos
;
?936?
struct?fown_struct f_owner;
?937?
const?struct?cred?*f_cred;
?938?
struct?file_ra_state f_ra;
?939
?940 u64 f_version
;
?941?
#ifdef?CONFIG_SECURITY
?942?
void?*f_security;
?943?
#endif
?944?
/* needed for tty driver, and maybe others */
?945?
void?*private_data;
?946
?947?
#ifdef?CONFIG_EPOLL
?948?
/* Used by fs/eventpoll.c to link all the hooks to this file */
?949?
struct?list_head f_ep_links;
?950?
#endif?/* #ifdef CONFIG_EPOLL */
?951?
struct?address_space?*f_mapping;
?952?
#ifdef?CONFIG_DEBUG_WRITECOUNT
?953?
unsigned?long?f_mnt_write_state;
?954?
#endif
?955?
};

從上面可以看到f_pos,記錄偏移值的,后面read的時候會用到, 大家好,我是Chinaunix的T-bagwell.下面繼續說ppos,其實就是這個loff_t *ppos,這個是通過file_pos_read來或得到的,

381?static?inline?loff_t file_pos_read(struct?file?*file)
382?
{
383?
return?file->f_pos;
384?
}

這個f_pos在每一次read的時候,都有可能會改變偏移量,繼續進入vfs_read去讀文件:

295 ssize_t vfs_read(struct?file?*file,?char?__user?*buf,?size_t?count,?loff_t?*pos)
296?{
297 ssize_t ret;
298
299?if?(!(file->f_mode?&?FMODE_READ))
300?return?-EBADF;
301?if?(!file->f_op?||?(!file->f_op->read?&&?!file->f_op->aio_read))
302?return?-EINVAL;
303?if?(unlikely(!access_ok(VERIFY_WRITE,?buf,?count)))
304?return?-EFAULT;
305
306 ret?=?rw_verify_area(READ,?file,?pos,?count);
307?if?(ret?>=?0)?{
308?count?=?ret;
309?if?(file->f_op->read)
310 ret?=?file->f_op->read(file,?buf,?count,?pos);
311?else
312 ret?=?do_sync_read(file,?buf,?count,?pos);
313?if?(ret?>?0)?{
314 fsnotify_access(file);
315 add_rchar(current,?ret);
316?}
317 inc_syscr(current);
318?}
319
320?return?ret;
321?}

大家好,我是ChinaUnix的T-bagwell 先確認一下要讀的文件是否可以去讀,如果不讓讀或者不讓寫的話,就只能直接推出去了,否則可以繼續上面的代碼里面有兩個read接口,一個是file的read,大家好,我是ChinaUnix的T-bagwell,轉載請注明出處,一個是do_sync_read,下面直接說file->f_op里面的read,這個read是在寫設備驅動的時候,或者文件系統加載的時候注冊的read 下面看設備驅動部分的read

231?static?ssize_t nvram_read(struct?file?*file,?char?__user?*buf,
232?size_t?count,?loff_t?*ppos)
233?{
234?unsigned?char?contents[NVRAM_BYTES];
235?unsigned?i?=?*ppos;
236?unsigned?char?*tmp;
237
238 spin_lock_irq(&rtc_lock);
239
240?if?(!__nvram_check_checksum())
241?goto?checksum_err;
242
243?for?(tmp?=?contents;?count--?>?0?&&?i?<?NVRAM_BYTES;?++i,?++tmp)
244?*tmp?=?__nvram_read_byte(i);
245
246 spin_unlock_irq(&rtc_lock);
247
248?if?(copy_to_user(buf,?contents,?tmp?-?contents))
249?return?-EFAULT;
250
251?*ppos?=?i;
252
253?return?tmp?-?contents;
254
255 checksum_err:
256 spin_unlock_irq(&rtc_lock);
257?return?-EIO;
258?}

這里就不用多說了,ppos是有需要的,當然,有些設備驅動里面可以不用這個ppos,比如keyboard的驅動一類的只要一個值的,但是如果想獲得很大的一段buffer的話,這個估計就有必要了。 接下來說do_sync_read文件,這個就要會想一下注冊文件系統時,對fops的注冊了 比如ext4文件系統里面,在ext4_file_super里面有個ext4_iget

struct?inode?*ext4_iget(struct?super_block?*sb,?unsigned?long?ino)


在這個接口里面會有注冊fops的操作:

5165?if?(S_ISREG(inode->i_mode))?{
5166 inode
->i_op?=?&ext4_file_inode_operations;
5167 inode
->i_fop?=?&ext4_file_operations;
5168 ext4_set_aops
(inode);
5169?
}?else?if?(S_ISDIR(inode->i_mode))?{
5170 inode
->i_op?=?&ext4_dir_inode_operations;
5171 inode
->i_fop?=?&ext4_dir_operations;
5172?
}?else?if?(S_ISLNK(inode->i_mode))?{
5173?
if?(ext4_inode_is_fast_symlink(inode))?{
5174 inode
->i_op?=?&ext4_fast_symlink_inode_operations;
5175 nd_terminate_link
(ei->i_data,?inode->i_size,
5176?
sizeof(ei->i_data)?-?1);
5177?
}?else?{
5178 inode
->i_op?=?&ext4_symlink_inode_operations;
5179 ext4_set_aops
(inode);
5180?
}
5181?
}?else?if?(S_ISCHR(inode->i_mode)?||?S_ISBLK(inode->i_mode)?||
5182 S_ISFIFO
(inode->i_mode)?||?S_ISSOCK(inode->i_mode))?{
5183 inode
->i_op?=?&ext4_special_inode_operations;
5184?
if?(raw_inode->i_block[0])
5185 init_special_inode
(inode,?inode->i_mode,
5186 old_decode_dev
(le32_to_cpu(raw_inode->i_block[0])));
5187?
else
5188 init_special_inode
(inode,?inode->i_mode,
5189 new_decode_dev
(le32_to_cpu(raw_inode->i_block[1])));
5190?
}?else?{

在這個里面可以知道了,為什么這里的是inode呢?這個在open里面應該有對應的答案,接下來繼續進繼續看文件操作部分

133?const?struct?file_operations ext4_file_operations?=?{
134?.llseek?=?generic_file_llseek,
135?.read?=?do_sync_read,
136?.write?=?do_sync_write,
137?.aio_read?=?generic_file_aio_read,
138?.aio_write?=?ext4_file_write,
139?.unlocked_ioctl?=?ext4_ioctl,
140?#ifdef?CONFIG_COMPAT
141?.compat_ioctl?=?ext4_compat_ioctl,
142?#endif
143?.mmap?=?ext4_file_mmap,
144?.open?=?ext4_file_open,
145?.release?=?ext4_release_file,
146?.fsync?=?ext4_sync_file,
147?.splice_read?=?generic_file_splice_read,
148?.splice_write?=?generic_file_splice_write,
149?};
150


其實文件操作就是和do_sync_read是一樣的操作,最終會進入到generic_file_aio_read,里面 generic_file_aio_read里面就是從快設備里面讀取內容了,到這里,如文件結束

原文地址: http://blog.chinaunix.net/uid-11344913-id-26743.html

總結

以上是生活随笔為你收集整理的Linux系统中,read文件过程分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。