色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

關于Linux文件系統的幾點注意事項

Q4MP_gh_c472c21 ? 來源:未知 ? 作者:李建兵 ? 2018-03-17 11:14 ? 次閱讀

做內核開發的朋友,可能對下面的代碼都很眼熟。

1.staticconststructfile_operationsxxx_fops={

2..owner=THIS_MODULE,

3..llseek=no_llseek,

4..write=xxx_write,

5..unlocked_ioctl=xxx_ioctl,

6..open=xxx_open,

7..release=xxx_release,

8.};

一般我們在xxx_open中會用類似如下的代碼分配一塊內存。

[cpp]view plaincopy

1.file->private_data=kmalloc(sizeof(structxxx),GFP_KERNEL);

然后在接下來的read/write/ioctl中,我們就可以通過file->private_data取到與此文件關聯的數據。

最后,在xxx_release中,我們會釋放file->private_data指向的內存。

如果只是上面這幾種流程訪問file->private_data所指向的數據,基本上不會出問題。

因為內核的文件系統框架已經做了很完善的處理。

對于迸發訪問,我們自己也可以通過鎖等機制來解決。

然而,我們通常還會在一些異步的流程中訪問file->private_data所指向的數據,這些異步流程可能由定時器,中斷,進程間通信等因素觸發。

并且,這些流程訪問數據時,沒有經過內核的文件系統框架。

那么這就有可能導致出現問題了。

下面我們先來看看內核文件系統框架的部分實現代碼,再來考慮如何規避可能出現的問題。我們的分析基于linux-3.10.102的內核源碼。

首先,要得到一個fd,必須先有一次調用C庫函數open的行為。而在C庫函數open返回之前,其他線程得不到fd,當然也就不會對此fd進行操作。等拿到fd時,open操作都已經完成了。

實際上,更夸張的情況還是有可能存在的。例如,可能由于程序的錯誤甚至是程序員故意構造特殊代碼,導致在open返回之前,其他線程就使用即將返回的fd進行文件操作了。這種情況,這里就不討論了。有興趣的朋友,可以自己鉆研內核代碼,看看會產生什么效果。

先看看文件打開操作的主要函數調用:

sys_open,do_sys_open,do_filp_open,fd_install,__fd_install。

安裝fd的操作如下。可見這里是對文件表加了鎖的,并且不是針對單個文件,是整體性的加鎖。

[cpp]view plaincopy

1.void__fd_install(structfiles_struct*files,unsignedintfd,

2.structfile*file)

3.{

4.structfdtable*fdt;

5.spin_lock(&files->file_lock);

6.fdt=files_fdtable(files);

7.BUG_ON(fdt->fd[fd]!=NULL);

8.rcu_assign_pointer(fdt->fd[fd],file);

9.spin_unlock(&files->file_lock);

10.}

讀寫操作,代碼結構非常相似。這里只看寫操作吧。其實現如下:

[cpp]view plaincopy

1.SYSCALL_DEFINE3(write,unsignedint,fd,constchar__user*,buf,

2.size_t,count)

3.{

4.structfdf=fdget(fd);

5.ssize_tret=-EBADF;

6.

7.if(f.file){

8.loff_tpos=file_pos_read(f.file);

9.ret=vfs_write(f.file,buf,count,&pos);

10.file_pos_write(f.file,pos);

11.fdput(f);

12.}

13.

14.returnret;

15.}

[cpp]view plaincopy

1.ssize_tvfs_write(structfile*file,constchar__user*buf,size_tcount,loff_t*pos)

2.{

3.ssize_tret;

4.

5.if(!(file->f_mode&FMODE_WRITE))

6.return-EBADF;

7.if(!file->f_op||(!file->f_op->write&&!file->f_op->aio_write))

8.return-EINVAL;

9.if(unlikely(!access_ok(VERIFY_READ,buf,count)))

10.return-EFAULT;

11.

12.ret=rw_verify_area(WRITE,file,pos,count);

13.if(ret>=0){

14.count=ret;

15.file_start_write(file);

16.if(file->f_op->write)

17.ret=file->f_op->write(file,buf,count,pos);

18.else

19.ret=do_sync_write(file,buf,count,pos);

20.if(ret>0){

21.fsnotify_modify(file);

22.add_wchar(current,ret);

23.}

24.inc_syscw(current);

25.file_end_write(file);

26.}

27.

28.returnret;

29.}

[cpp]view plaincopy

1.ssize_tdo_sync_write(structfile*filp,constchar__user*buf,size_tlen,loff_t*ppos)

2.{

3.structioveciov={.iov_base=(void__user*)buf,.iov_len=len};

4.structkiocbkiocb;

5.ssize_tret;

6.

7.init_sync_kiocb(&kiocb,filp);

8.kiocb.ki_pos=*ppos;

9.kiocb.ki_left=len;

10.kiocb.ki_nbytes=len;

11.

12.ret=filp->f_op->aio_write(&kiocb,&iov,1,kiocb.ki_pos);

13.if(-EIOCBQUEUED==ret)

14.ret=wait_on_sync_kiocb(&kiocb);

15.*ppos=kiocb.ki_pos;

16.returnret;

17.}

可以看出,讀寫操作是無鎖的。也不好加鎖,因為讀寫操作,還有ioctl,有可能阻塞。如果需要鎖,用戶自己可以使用文件鎖,《UNIX環境高級編程》中有關于文件鎖的描述。

不過fdget與fdput中包含了一些rcu方面的操作,那是為了能夠與close fd的操作迸發進行。

另外,可以看出,如果只實現一個f_op->aio_write,也是可以支持C庫函數write的。

再來看看ioctl的實現。

[cpp]view plaincopy

1.SYSCALL_DEFINE3(ioctl,unsignedint,fd,unsignedint,cmd,unsignedlong,arg)

2.{

3.interror;

4.structfdf=fdget(fd);

5.

6.if(!f.file)

7.return-EBADF;

8.error=security_file_ioctl(f.file,cmd,arg);

9.if(!error)

10.error=do_vfs_ioctl(f.file,fd,cmd,arg);

11.fdput(f);

12.returnerror;

13.}

對于非常規文件,或者常規文件中文件系統特有的命令,最終都會走到

filp->f_op->unlocked_ioctl

另外,ioctl也是無鎖的。同時,流程中包含了fdget與fdput,這一點與read/write一樣。

再來看看關閉文件的操作。系統調用sys_close的實現如下(fs/open.c)

[cpp]view plaincopy

1.SYSCALL_DEFINE1(close,unsignedint,fd)

2.{

3.intretval=__close_fd(current->files,fd);

4.

5./*can'trestartclosesyscallbecausefiletableentrywascleared*/

6.if(unlikely(retval==-ERESTARTSYS||

7.retval==-ERESTARTNOINTR||

8.retval==-ERESTARTNOHAND||

9.retval==-ERESTART_RESTARTBLOCK))

10.retval=-EINTR;

11.

12.returnretval;

13.}

可見主要工作是__close_fd函數(fs/file.c)完成的,其代碼如下。可見他是對進程的文件表加了鎖的。因此,open、close操作是有互斥的,并且不是針對某一文件的互斥,而是整體的互斥。

對于close一個fd時,其他cpu上的線程若正要或正在讀寫此fd怎么辦?可以看出,close操作并不會為此等待,而是直接繼續操作。

其中的rcu_assign_pointer(fdt->fd[fd], NULL);清除了此fd與file結構的關聯,因此在此之后通過此fd已經訪問不到相應的file結構了。至于在此之前就發起了的且尚未結束的訪問怎么處理,答案是在filp_close中處理。

[cpp]view plaincopy

1.int__close_fd(structfiles_struct*files,unsignedfd)

2.{

3.structfile*file;

4.structfdtable*fdt;

5.

6.spin_lock(&files->file_lock);

7.fdt=files_fdtable(files);

8.if(fd>=fdt->max_fds)

9.gotoout_unlock;

10.file=fdt->fd[fd];

11.if(!file)

12.gotoout_unlock;

13.rcu_assign_pointer(fdt->fd[fd],NULL);

14.__clear_close_on_exec(fd,fdt);

15.__put_unused_fd(files,fd);

16.spin_unlock(&files->file_lock);

17.returnfilp_close(file,files);

18.

19.out_unlock:

20.spin_unlock(&files->file_lock);

21.return-EBADF;

22.}

filp_close又調用了fput, 后者的相關代碼如下。可見當前任務若非內核線程,接下來就是走____fput,否則就是走delayed_fput。

但是最終都是走__fput,__fput中會調用file->f_op->release,即我們的xxx_release。

不過,從fput代碼可以看出,____fput會由rcu相關的work觸發。因此,可以預見當____fput被調用時,已經沒有已經發生且尚未結束的針對此文件的訪問流程了。

[cpp]view plaincopy

1.staticvoid____fput(structcallback_head*work)

2.{

3.__fput(container_of(work,structfile,f_u.fu_rcuhead));

4.}

5.

6.

7.voidflush_delayed_fput(void)

8.{

9.delayed_fput(NULL);

10.}

11.

12.staticDECLARE_WORK(delayed_fput_work,delayed_fput);

13.

14.voidfput(structfile*file)

15.{

16.if(atomic_long_dec_and_test(&file->f_count)){

17.structtask_struct*task=current;

18.

19.if(likely(!in_interrupt()&&!(task->flags&PF_KTHREAD))){

20.init_task_work(&file->f_u.fu_rcuhead,____fput);

21.if(!task_work_add(task,&file->f_u.fu_rcuhead,true))

22.return;

23.}

24.

25.if(llist_add(&file->f_u.fu_llist,&delayed_fput_list))

26.schedule_work(&delayed_fput_work);

27.}

28.}

現在再來想想,我們上面提到的那些訪問file->private_data所指向的數據的異步流程,這些流程并沒有走文件系統框架。

會不會出現這種情況,xxx_release已經執行過了,可是異步流程卻還來訪問file->private_data所指向的數據呢?

其實xxx_release不妨不要釋放file->private_data指向的內存,而是標記一下他的狀態為已關閉。然后異步流程再訪問此數據時,先檢查一下狀態。

若為已關閉,則妥善處理并釋放即可。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11292

    瀏覽量

    209333

原文標題:關于Linux文件系統的幾點注意事項

文章出處:【微信號:gh_c472c2199c88,微信公眾號:嵌入式微處理器】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    使用HTTP協議有哪幾點注意事項

    HTTP協議是什么?HTTP協議的工作原理是什么?使用HTTP協議有哪幾點注意事項
    發表于 09-29 09:23

    嵌入式工程模板搭建幾點注意事項

    嵌入式工程模板搭建幾點注意事項—以STM32l475VET6為例一. 系統時鐘初始化函數搭建工程基本模板,除過移植官方提供的相關文件外,另一個關鍵點是編寫
    發表于 02-08 07:07

    Linux文件系統課程

    本章學習目標理解什么是文件系統了解文件系統工作原理理解Fedora Core Linux文件系統的結構掌握Fedora Core Linux
    發表于 04-10 17:07 ?0次下載

    Linux文件系統簡介

    Linux文件系統簡介 什么是根文件   根文件系統首先是一種文件系統,但是相對于普通的文件系統
    發表于 04-21 17:01 ?5111次閱讀

    玩轉Linux,先把文件系統搞懂

    Linux 支持多種文件系統,包括 ext2 、 ext3 、 vfat 、 ntfs 、 iso9660 、 jffs 、 romfs 和 nfs 等,為了對各類文件系統進行統一管理, Li
    發表于 08-16 10:50 ?2073次閱讀
    玩轉<b class='flag-5'>Linux</b>,先把<b class='flag-5'>文件系統</b>搞懂

    Linux設備驅動開發詳解》第5章、Linux文件系統與設備文件系統

    Linux設備驅動開發詳解》第5章、Linux文件系統與設備文件系統
    發表于 10-27 14:13 ?0次下載
    《<b class='flag-5'>Linux</b>設備驅動開發詳解》第5章、<b class='flag-5'>Linux</b><b class='flag-5'>文件系統</b>與設備<b class='flag-5'>文件系統</b>

    文件系統是什么?淺談EXT文件系統歷史

    在先前關于Linux文件系統的文章中,我很想去深入地討論更多EXT文件系統的特性的信息。所以,首先讓我們來回答這個問題:什么是文件系統?一個
    發表于 06-28 09:03 ?5694次閱讀
    <b class='flag-5'>文件系統</b>是什么?淺談EXT<b class='flag-5'>文件系統</b>歷史

    Linux 內核/sys 文件系統介紹

    linux2.6內核引入sysfs文件系統,sysfs可以看成與proc,devfs和devpty同類別的文件系統,該文件系統是虛擬的文件系統
    發表于 04-25 16:20 ?4291次閱讀
    <b class='flag-5'>Linux</b> 內核/sys <b class='flag-5'>文件系統</b>介紹

    可以了解的Linux 文件系統結構

    Linux中的文件是什么?它的文件系統又是什么?那些配置文件又在哪里?我下載好的程序保存在哪里了?在 Linux
    發表于 04-27 14:06 ?716次閱讀
    可以了解的<b class='flag-5'>Linux</b> <b class='flag-5'>文件系統</b>結構

    Linux最新UBI文件系統介紹

    嵌入式linux中文站關注嵌入式linux文件系統的發展。在linux-2.6.27以前,談到Flash文件系統,大家很多時候多會想到cra
    發表于 04-27 19:37 ?6385次閱讀

    Linux嵌入式文件系統如何構建

    Linux支持多種文件系統,同樣,嵌入式Linux也支持多種文件系統。雖然在嵌入式系統中,由于資源受限的原因,它的
    發表于 06-18 09:23 ?992次閱讀

    Linux文件系統解析

    Linux 中,最直觀、最可見的部分就是 文件系統(file system)。下面我們就來一起探討一下關于 Linux 中國的文件系統
    的頭像 發表于 09-16 11:29 ?2458次閱讀
    <b class='flag-5'>Linux</b><b class='flag-5'>文件系統</b>解析

    適用于Linux的最佳通用文件系統 Linux文件系統的安裝

    為您的計算機選擇正確的文件系統可能是一個困難的過程。您可能會想知道:為什么文件系統很重要?有沒有適用于安裝 Linux 的特定文件系統? 事實證明,有兩種
    發表于 08-03 10:22 ?339次閱讀
    適用于<b class='flag-5'>Linux</b>的最佳通用<b class='flag-5'>文件系統</b> <b class='flag-5'>Linux</b><b class='flag-5'>文件系統</b>的安裝

    Linux文件系統特點

    Linux文件系統特點 文件系統要有嚴格的組織形式,使得文件能夠以塊為單位進行存儲。 文件系統中也要有索引區,用來方便查找一個
    的頭像 發表于 11-09 14:48 ?1171次閱讀
    <b class='flag-5'>Linux</b>的<b class='flag-5'>文件系統</b>特點

    Linux文件系統的掛載過程

    Linux文件系統(rootfs)是Linux系統中所有其他文件系統和目錄的起點,它是內核啟動時掛載的第一個
    的頭像 發表于 10-05 16:50 ?404次閱讀
    主站蜘蛛池模板: 日韩精品真人荷官无码| 麻豆人妻无码性色AV| 在线综合 亚洲 欧美| 清晨紧湿爱运动h高h| 俄罗斯bbbbbbbbb大片| 亚洲 欧美 日韩 国产 视频| 高清 仑乱 一级 a| 亚洲女人毛片| 轻点灬大ji巴太粗太双性高h| 国产AV精品无码免费看| 亚洲日韩天堂在线中文字幕| 久久久无码精品无码国产人妻丝瓜| 最近最新中文字幕MV高清在线| 欧美亚洲国产激情一区二区| 国产精品久久久久久亚洲毛片| 伊人影院久久| 无码欧美毛片一区二区三在线视频| 久cao在线香蕉| 俄罗斯女肥臀大屁BBW| 猪蜜蜜网站在线观看电视剧| 视频成人永久免费看| 免费果冻传媒2021在线看| 国产在线亚洲精品观| 怪物高h粗暴无尽| XXX国产麻豆HD真实乱| 一区一区三区产品| 爽爽影院线观看免费| 男女又黄又刺激B片免费网站| 国产人妻人伦精品久久无码| www.伊人网| 97精品少妇偷拍蜜桃AV| 一区三区在线专区在线| 少妇内射视频播放舔大片| 欧美一区二区视频高清专区| 麻豆精品传媒2021网站入口| 国精产品一区一区三区有限| 高清国产激情视频在线观看| 99re在线播放| 99久久伊人一区二区yy5o99| 伊人久久青草| 伊人最新网址|