成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Linux下的文件輸入/輸出端口

系統 Linux
a small, nonnegative integer for use in subsequent system calls (read(2), write(2), lseek(2), fcntl(2), etc.) ($man 2 open). 一個程序開始運行時一般會有3個已經打開的文件描述符。

文件描述符(File Descriptor)

a small, nonnegative integer for use in subsequent system calls (read(2), write(2), lseek(2), fcntl(2), etc.) ($man 2 open). 一個程序開始運行時一般會有3個已經打開的文件描述符:

  • 0 :STDIN_FIFLENO,標準輸入stdin
  • 1 :STDOUT_FILENO,標準輸出stdout
  • 2 :STDERR_FILENO,標準錯誤stderror

fd原理 

  • fd從0開始, 查找最小的未被使用的描述符, 把文件表指針與文件表描述符建立對應關系(VS pid是一直向上漲,滿了再回來找)
  • 文件描述符就是一個int, 用于代表一個打開的文件, 但是文件的管理信息不能夠不是存放在文件描述符中,當使用open()函數打開一個文件時, OS會將文件的相關信息加載到文件表等數據結構中, 但出于安全和效率等因素的考慮, 文件表等數據結構并不適合直接操作, 而是給該結構指定一個編號, 使用編號來進行操作, 該編號就是文件描述符
  • OS會為每個進程內部維護一張文件描述符總表, 當有新的文件描述符需求時, 會去總表中查找最小的未被使用的描述符返回, 文件描述符雖然是int類型, 但其實是非負整數, 也就是0~OPEN_MAX(當前系統中為1024), 其中0,1,2已被系統占用,分別表示stdin, stdout,stderror
  • 使用close()關閉fd時, 就是將fd和文件表結構之間的對應關系從總表中移除, 但不一定會刪除文件表結構, 只有當文件表沒有與其他任何fd對應時(也就是一個文件表可以同時對應多個fd)才會刪除文件表, close()也不會改變文件描述符本身的整數值, 只會讓該文件描述符無法代表一個文件而已
  • duplicate fdVS copy fd:dup是把old_fd對應的文件表指針復制給new_fd, 而不是int new_fd=old_fd
  • UNIX使用三種數據結構描述打開的文件:每個進程中用于描述當前進程打開文件的文件描述符表,表示當前文件狀態的文件狀態標識表,和用于找到文件i節點(索引節點)的V節點表,Linux中并不使用這種Vnode結構,取而代之的是一種通用的inode結構,但本質沒有區別,inode是在讀取文件時通過文件系統從磁盤中導入的文件位置

      

 

 

 

文件描述符標志(File Descriptor Flag)

當下的系統只有一個文件描述符標志close-on-exec,僅僅是一個標志,當進程fork一個子進程的時候,在子進程中調用了exec函數時就用到了該標志。意義是執行exec前是否要關閉這個文件描述符。

  • 一般我們會調用exec執行另一個程序,此時會用全新的程序替換子進程的正文,數據,堆和棧等。此時保存文件描述符的變量當然也不存在了,我們就無法關閉無用的文件描述符了。所以通常我們會fork子進程后在子進程中直接執行close關掉無用的文件描述符,然后再執行exec。但是在復雜系統中,有時我們fork子進程時已經不知道打開了多少個文件描述符(包括socket句柄等),這此時進行逐一清理確實有很大難度。我們期望的是能在fork子進程前打開某個文件句柄時就指定好:這個句柄我在fork子進程后執行exec時就關閉”。所以就有了 close-on-exec
  • 每個文件描述符都有一個close-on-exec標志。在系統默認情況下,這個標志***一位被設置為0。即關閉了此標志。那么當子進程調用exec函數,子進程將不會關閉該文件描述符。此時,父子進程將共享該文件,它們具有同一個文件表項,也就有了同一個文件偏移量等。
  • fcntl()的FD_CLOEXEC和open()的O_CLOEXEC用來設置文件的close-on-exec,當將close-on-exec標志置為1時,即開啟此標志, 此時子進程調用exec函數之前,系統就已經讓子進程將此文件描述符關閉。

Note:雖然新版本支持在open時設置CLOEXEC,但是在編譯的時候還是會提示錯誤 - error: ‘O_CLOEXEC’ undeclared (first use in this function)。這個功能需要設置宏(_GNU_SOURCE)打開。

  1. #define _GNU_SOURCE //在源代碼中加入    
  1. -D_GNU_SOURCE //在編譯參數中加入 

文件狀態標志(File Status Flag)

File status flags 用來表示打開文件的屬性,file status flag可以通過duplicate一個文件描述符來共享同一個打開的文件的狀態,而file descrptor flag則不行

  • Access Modes: 指明文件的access方式:read-only, write-only,read-write。通過open()設置,通過fcntl()返回,但不能被改變
  • Open-time Flags: 指明在open()執行的時候的操作,open()執行完畢這個flag不會被保存
  • Operating Modes: 影響read,write操作,通過open()設置,但可以用fcntl()讀取或改變

open()

  1. //給定一個文件路徑名,按照相應的選項打開文件,就是將一個fd和文件連接到一起,成功返回文件描述符,失敗返回-1設errno 
  2.  
  3. #include<fcntl.h> 
  4.  
  5. int open(const char *pathname, int flags) 
  6.  
  7. int open(const char *pathname, int flags, mode_t mode) 
  8.  
  9. //不是函數重載,C中沒有重載, 是可變長參數列表 
  10. //pathname:文件或設備路徑 
  11. //flags :file status flags=Access mode+Open-time flags+Operating Modes、 
  12. /*Access Mode(必選一個): 
  13. O_RDONLY:0 
  14. O_WRONLY:1 
  15. O_RDWR:2 
  16. */ 
  17. /*Open-time Flags(Bitwise Or): 
  18. O_CLOEXEC   :為新打開的文件描述符使能close-on-exec。可以避免程序再用fcntl()的F_SETFD來設置FD_CLOEXEC 
  19. O_CREAT     :如果文件不存在就創建文件,并返回它的文件描述符,如果文件存在就忽略這個選項,必須在保護模式下使用,eg:0664 
  20. O_DIRECTORY :如果opendir()在一個FIFO或tape中調用的話,這個選項可以避免denial-of-service問題,  如果路徑指向的不是一個目錄,就會打開失敗。 
  21. O_EXCL      :確保open()能夠穿件一個文件,如果文件已經存在,則會導致打開失敗,總是和O_CREAT一同使用。 
  22. O_NOCTTY    :如果路徑指向一個終端設備,那么這個設備不會成為這個進程的控制終端,即使這個進程沒有一個控制終端 
  23. O_NOFOLLOW  :如果路徑是一個符號鏈接,就打開它鏈接的文件//If pathname is a symbolic link, then the open fails. 
  24. O_TMPFILE   :創建一個無名的臨時文件,文件系統中會創建一個無名的inode,當***一個文件描述符被關閉的時候,所有寫入這個文件的內容都會丟失,除非在此之前給了它一個名字 
  25. O_TRUNC     :清空文件 
  26. O_TTY_INIT 
  27. *//*Operating Modes(Bitwise Or
  28. O_APPEND    :以追加的方式打開文件, 默認寫入結尾,在當下的Unix/Linux系統中,這個選項已經被定義為一個原子操作   
  29. O_ASYNC     :使能signal-driven I/O 
  30. O_DIRECT    :試圖最小化來自I/O和這個文件的cache effect//Try to minimize cache effects of the I/O to and from this  file. 
  31. O_DSYNC     :每次寫操作都會等待I/O操作的完成,但如果文件屬性的更新不影響讀取剛剛寫入的數據的話,就不會等待文件屬性的更新    。 
  32. O_LARGEFILE :允許打開一個大小超過off_t(但沒超過off64_t)表示范圍的文件 
  33. O_NOATIME   :不更改文件的st_time(last access time
  34. O_NONBLOCK /O_NDELAY :如果可能的話,用nonblock模式打開文件 
  35. O_SYNC      :每次寫操作都會等待I/O操作的完成,包括write()引起的文件屬性的更新。 
  36. O_PATH      :獲得一個能表示文件在文件系統中位置的文件描述符 
  1. #include<fcntl.h> 
  2.  
  3. #include<stdlib.h> 
  4.  
  5. int fd=open("b.txt",O_RDWR|O_CREAT|O_EXCL,0664); 
  6. if(-1==fd) 
  7.     perror("open"),exit(-1);  

FA:猜想有以下模型:用一串某一位是1其余全是0的字符串表示一個選項, 選項們作 “按位與”就可得到0/1字符串, 表示整個flags的狀態, Note: 低三位表示Access Mode

creat()

等價于以O_WRONLY |O_TRUNC|O_CREAT的flag調用open()

  1. #include<fcntl.h> 
  2.  
  3. int creat(const char *pathname, mode_t mode); 

dup()、dup2()、dup3()

  1. /復制一個文件描述符的指向,新的文件描述符的flags和原來的一樣,成功返回new_file_descriptor, 失敗返回-1并設errno 
  2.  
  3. #include <unistd.h> 
  4.  
  5. int dup(int oldfd);           //使用未被占用的最小的文件描述符編號作為新的文件描述符 
  6.  
  7. int dup2(int oldfd, int newfd); 
  1. #include <fcntl.h>       
  2. #include <unistd.h> 
  3.  
  4. int dup3(int oldfd, int newfd, int flags); 
  1. #include<unistd.h> 
  2.  
  3. #include<stdlib.h> 
  4.  
  5. int res=dup2(fd,fd2); 
  6. if(-1==res){ 
  7.         perror("dup2"),exit(-1); 
  8.   

 

 

 

read()

  1. //從fd對應的文件中讀count個byte的數據到以buf開頭的緩沖區中,成功返回成功讀取到的byte的數目,失敗返回-1設errno 
  2.  
  3. #include <unistd.h> 
  4.  
  5. ssize_t read(int fd, void *buf, size_t count); 
  1. #include <unistd.h> 
  2.  
  3. #include<stdlib.h> 
  4.  
  5. int res=read(fd,buf,6); 
  6. if(-1==fd) 
  7.     perror("read"),exit(-1);  

write()

  1. //從buf指向的緩沖區中讀取count個byte的數據寫入到fd對應的文件中,成功返回成功寫入的byte數目,文件的位置指針會向前移動這個數目,失敗返回-1設errno 
  2.  
  3. #include <unistd.h> 
  4.  
  5. ssize_t write(int fd, const void *buf, size_t count);//不需要對buf操作, 所以有const, VS read()沒有const 
  1. #include <unistd.h> 
  2.  
  3. #include<stdlib.h> 
  4.  
  5. int res=write(fd,"hello",sizeof("hello")); 
  6. if(-1==res) 
  7.     perror("write"),exit(-1);  

Note: 上例中即使只有一個字符’A’,也要寫”A”,因為”A”才是地址,’A’只是個int

lseek()

l 表示long int, 歷史原因

  1. //根據移動基準whence和移動距離offset對文件的位置指針進行重新定位,返回移動后的位置指針與文件開頭的距離,失敗返回-1設errno 
  2.  
  3. #include <unistd.h> 
  4.  
  5. #include <sys/types.h> 
  6.  
  7. off_t lseek(int fd, off_t offset, int whence); 
  8. /*whence: 
  9. SEEK_SET:以文件開頭為基準進行偏移,0一般不能向前偏 
  10. SEEK_CUR:以當前位置指針的位置為基準進行偏移,1向前向后均可 
  11. SEEK_END:以文件的結尾為基準進行偏移,2向前向后均可向后形成”文件空洞”  
  1. #include<unistd.h> 
  2.  
  3. #include<stdlib> 
  4.  
  5. int len=lseek(fd,-3,SEEK_SET); 
  6. if(-1==len){ 
  7.         perror("lseek"),exit(-1); 
  8.  

fcntl()

  1. //對fd進行各種操作,成功返回0,失敗返回-1設errno 
  2. #include <unistd.h> 
  3. #include <fcntl.h> 
  4.  
  5. int fcntl(int fd, int cmd, ... );       //...表示可變長參數 
  6. /*cmd: 
  7. Adversory record locking: 
  8. F_SETLK(struct flock*)  //設建議鎖 
  9. F_SETLKW(struct flock*) //設建議鎖,如果文件上有沖突的鎖,且在等待的時候捕獲了一個信號,則調用被打斷并在信號捕獲之后立即返回一個錯誤,如果等待期間沒有信號,則一直等待  
  10. F_GETLK(struct flock*)  //嘗試放鎖,如果能放鎖,則不會放鎖,而是返回一個含有F_UNLCK而其他不變的l_type類型,如果不能放鎖,那么fcntl()會將新類型的鎖加在文件上,并把當前PID留在鎖上 
  11. Duplicating a file descriptor: 
  12. F_DUPFD (int)       //找到>=arg的最小的可以使用的文件描述符,并把這個文件描述符用作fd的一個副本 
  13. F_DUPFD_CLOEXEC(int)//和F_DUPFD一樣,除了會在新的文件描述符上設置close-on-execF_GETFD (void)      //讀取fd的flag,忽略arg的值 
  14. F_SETFD (int)       //將fd的flags設置成arg的值. 
  15. F_GETFL (void)      //讀取fd的Access Mode和其他的file status flags; 忽略arg 
  16. F_SETFL (long)      //設置file status flags為arg 
  17. F_GETOWN(void)      //返回fd上接受SIGIO和SIGURG的PID或進程組ID 
  18. F_SETOWN(int)       //設置fd上接受SIGIO和SIGURG的PID或進程組ID為arg 
  19. F_GETOWN_EX(struct f_owner_ex*) //返回當前文件被之前的F_SETOWN_EX操作定義的文件描述符R 
  20. F_SETOWN_EX(struct f_owner_ex*) //和F_SETOWN類似,允許調用程序將fd的I/O信號處理權限直接交給一個線程,進程或進程組 
  21. F_GETSIG(void)      //當文件的輸入輸出可用時返回一個信號 
  22. F_SETSIG(int)       //當文件的輸入輸出可用時發送arg指定的信號 
  23. */ 
  24.  
  25. /*…:     
  26. 可選參素,是否需要得看cmd,如果是加鎖,這里應是struct flock* 
  27. struct flock { 
  28.     short l_type;   //%d Type of lock: F_RDLCK(讀鎖), F_WRLCK(寫鎖), F_UNLCK(解鎖) 
  29.     short l_whence; //%d How to interpret l_start, 加鎖的位置參考標準:SEEK_SET, SEEK_CUR, SEEK_END 
  30.     off_t l_start;  //%ld Starting offset for lock,     加鎖的起始位置 
  31.     off_t l_len;    //%ld Number of bytes to lock , 鎖定的字節數 
  32.     pid_t l_pid;    // PID of process blocking our lock, (F_GETLK only)加鎖的進程號,,默認給-1}; 
  33. */  

建議鎖(Adversory Lock)

限制加鎖,但不限制讀寫, 所以只對加鎖成功才讀寫的程序有效,用來解決不同的進程 同時對同一個文件的同一個位置 “寫”導致的沖突問題

讀鎖是一把共享鎖(S鎖):共享鎖+共享鎖+共享鎖+共享鎖+共享鎖+共享鎖

寫鎖是一把排他鎖(X鎖):永遠孤苦伶仃

釋放鎖的方法(逐級提高):

  • 將鎖的類型改為:F_UNLCK, 再使用fcntl()函數重新設置
  • close()關閉fd時, 調用進程在該fd上加的所有鎖都會自動釋放
  • 進程結束時會自動釋放所有該進程加過的文件鎖

Q:為什么加了寫鎖還能gedit或vim寫???

A:可以寫, 鎖只可以控制能否加鎖成功, 不能控制對文件的讀寫, 所以叫”建議”鎖, 我加了鎖就是不想讓你寫, 你非要寫我也沒辦法. vim/gedit不通過能否加鎖成功來決定是否讀寫, 所以可以直接上

Q: So如何實現文件鎖控制文件的讀寫操作????

A:可以在讀操作前嘗試加讀鎖, 寫操作前嘗試加寫鎖, 根據能否加鎖成功決定能否進行讀寫操作

  1. int fd=open("./a.txt",O_RDWR);                  //得到fd 
  2.  
  3. if(-1==fd) 
  4.     perror("open"),exit(-1);struct flock lock={F_RDLCK,SEEK_SET,2,5,-1};    //設置鎖   //此處從第3個byte開始(包含第三)鎖5byte 
  5.  
  6. int res=fcntl(fd,F_SETLK,&lock);                //給fd加鎖 
  7.  
  8. if(-1==res) 
  9.     perror("fcntl"),exit(-1);  

ioct1()

這個函數可以實現其他文件操作函數所沒有的功能,大多數情況下都用在設備驅動程序里,每個設備驅動程序可以定義自己專用的一組ioctl命令,系統則為不同種類的設備提供通用的ioctl命令

  1. //操作特殊文件的設備參數,成功返回0,失敗返回-1設errno 
  2.  
  3. #include <sys/ioctl.h> 
  4.  
  5. int ioctl(int d, int request, ...); 
  6. //d:an open file descriptor.//request: a device-dependent  request  code 

close()

  1. //關閉fd,這樣這個fd就可以重新用于連接其他文件,成功返回0,失敗返回-1設errno 
  2.  
  3. #include <unistd.h> 
  4.  
  5. int close(int fd); 
  1. #include <unistd.h> 
  2. #include<stdlib.h> 
  3.  
  4. int res=close(fd); 
  5. if(-1==res) 
  6.         perror("close"),exit(-1);  
責任編輯:龐桂玉 來源: 嵌入式Linux中文站
相關推薦

2009-12-03 10:14:06

Linux端口

2011-03-16 10:12:27

LinuxIptables端口轉發

2022-11-10 15:08:44

Linux輸入輸出

2021-06-24 10:24:57

Linux輸入輸出設備Interface

2014-09-04 11:39:43

Linux

2009-12-23 10:57:20

nohup命令

2019-06-03 15:52:21

WindowsLinux端口

2021-10-19 11:23:02

Linux端口隨機

2012-05-10 13:49:44

Linux文件系統

2009-08-06 19:37:17

2023-10-30 08:53:36

Python輸入輸出

2009-09-16 08:57:17

Linux端口Linux運行

2011-11-28 09:25:36

Java輸入輸出

2009-11-23 10:14:10

Linuxroute命令輸出信息

2009-11-06 10:02:45

LinuxISO文件操作系統

2016-12-22 09:02:35

Linux誤刪文件

2017-02-28 20:00:17

Linux文件系統對比

2019-10-21 08:56:36

Linux日志文件拆分

2010-11-29 14:24:06

Linux軟件管理

2009-03-09 19:48:17

LinuxSunPinyin拼音輸入法
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 91精品国产91综合久久蜜臀 | 久久久免费精品 | 久久精品视频一区二区三区 | 天天综合天天 | 99re6在线视频 | 亚洲高清成人 | 欧美a区 | 日韩成人免费视频 | avtt国产| 国产免费一级一级 | 丝袜天堂 | 丝袜美腿一区二区三区动态图 | 一区二区在线视频 | 成人在线免费av | 亚洲综合无码一区二区 | 成人av免费在线观看 | 日韩电影a | 国产在线中文字幕 | 欧美一级久久久猛烈a大片 日韩av免费在线观看 | 国产1区在线 | 日韩有码一区 | 久久综合一区 | 午夜私人影院在线观看 | 婷婷国产一区 | 大乳boobs巨大吃奶挤奶 | 91免费小视频 | 亚洲第一网站 | 中文字幕一区在线观看视频 | 国产精品一区二区三区久久久 | 亚洲欧美日韩精品久久亚洲区 | 亚洲欧洲精品在线 | 成人免费视频播放 | 色永久| 日日摸夜夜爽人人添av | 国产日韩精品一区 | 狠狠操电影 | 亚洲精品高清视频 | 国产av毛片| 亚欧洲精品在线视频免费观看 | 色噜噜狠狠色综合中国 | 久久一起草 |