 Open函(han)數的(de)flag和fcntl詳解
							時間:2018-09-27      來源:未知
							Open函(han)數的(de)flag和fcntl詳解
							時間:2018-09-27      來源:未知 
							1:文件讀寫權限
Linux中(zhong)文件有(you)讀寫權(quan)(quan)限,我們在open打開文件時也可以附(fu)帶一(yi)定(ding)的權(quan)(quan)限說明。比如
O_RDLNLY就(jiu)表(biao)示(shi)以只讀(du)方式打開(kai),O_WRONLY表(biao)示(shi)以只寫方式打開(kai),O_RDWR表(biao)示(shi)以可(ke)讀(du)可(ke)寫方式打開(kai)。當(dang)我們(men)在open文件(jian)時(shi)附帶了某種權限后,打開(kai)的文件(jian)就(jiu)只能按(an)照(zhao)該權限來操作。
本文引用地址://fsbing.cn/emb/Column/7285.html
2:更改文件內容
當我們open已經存在并且內部有內容的文(wen)件(jian)會出(chu)現(xian)幾種(zhong)情況,
2-1:原來內容消失(shi)使用O_TRUNC標(biao)志。
2-2:新內容添加(jia)到原內容后面使用O_APPEND標志
3:退出進程或程序
1:dang程序在前面(mian)的(de)操作執行(xing)失敗(bai)導致后(hou)面(mian)的(de)操作都(dou)不可能進行(xing)下去時,我們應在前面(mian)的(de)錯誤監測(ce)程序中(zhong)結束整個程序,不應該讓程序繼續運(yun)行(xing)下去。
2:在main函數中(zhong)使用return關鍵字,一般原則(ze)是程序正(zheng)常(chang)終止(zhi)return 0, 程序異常(chang)終止(zhi)return -1,
3:正(zheng)式終(zhong)止(zhi)程(cheng)序(xu)應使用exit或_exit,一般原則(ze)是進程(cheng)正(zheng)常終(zhong)止(zhi)exit(0),程(cheng)序(xu)異常終(zhong)止(zhi)exit(-1)。
4:阻塞與非阻塞
1:如果(guo)某個函(han)(han)(han)(han)數(shu)(shu)是阻塞的(de),則我們(men)調用(yong)(yong)該函(han)(han)(han)(han)數(shu)(shu)時當前(qian)進程有可能被(bei)阻塞住(實質是該函(han)(han)(han)(han)數(shu)(shu)內部要(yao)完成(cheng)的(de)事情條(tiao)件(jian)不(bu)具(ju)備,當前(qian)沒(mei)法(fa)做,要(yao)等待(dai)條(tiao)件(jian)成(cheng)熟),函(han)(han)(han)(han)數(shu)(shu)被(bei)阻塞住了(le)就(jiu)不(bu)能立(li)(li)刻返回;如果(guo)某個函(han)(han)(han)(han)數(shu)(shu)是非阻塞的(de),那么我們(men)調用(yong)(yong)這個函(han)(han)(han)(han)數(shu)(shu)后一定會立(li)(li)即返回,但是函(han)(han)(han)(han)數(shu)(shu)有沒(mei)有完成(cheng)任務不(bu)一定。
(2)阻(zu)塞和非阻(zu)塞是兩種不同的設(she)計思路,并沒(mei)有(you)(you)好壞;總(zong)的來(lai)說,阻(zu)塞式(shi)的結(jie)果有(you)(you)保(bao)障但(dan)是時間(jian)沒(mei)保(bao)障;非阻(zu)塞式(shi)的時間(jian)有(you)(you)保(bao)障但(dan)結(jie)果沒(mei)保(bao)障。
(3)操作系(xi)統(tong)提(ti)供的(de)API和由API封裝而成的(de)庫函(han)數,有很多本身就是被(bei)設計為阻(zu)塞式(shi)(shi)或者非阻(zu)塞式(shi)(shi)的(de),所以我們應用程序(xu)調用這些函(han)數的(de)時必須明確該函(han)數是阻(zu)塞式(shi)(shi)還是非阻(zu)塞式(shi)(shi)。
(4)默認情況下,我(wo)們open某(mou)個(ge)文件(jian)時(shi)是阻塞(sai)式的(de)(在打(da)開該(gai)文件(jian)后讀(du)寫(xie)該(gai)文件(jian)時(shi)若出現問題則會導致阻塞(sai)),如果希望以(yi)非(fei)阻塞(sai)的(de)方式打(da)開文件(jian),則flag中要加O_NONBLOCK標志;阻塞(sai)與非(fei)阻塞(sai)只(zhi)作(zuo)用于設備文件(jian)(linux的(de)硬件(jian)設備如串(chuan)口、I2C通(tong)訊器件(jian)、LCD),而不作(zuo)用于普通(tong)文件(jian)。
功能描述:根(gen)據文(wen)件描述詞來(lai)操作(zuo)文(wen)件的特性(xing)。
  #include
  #include
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
[描述]
fcntl()針(zhen)對(文件)描(miao)(miao)述(shu)符提供控(kong)制。參數fd是被(bei)參數cmd操作(如下面的描(miao)(miao)述(shu))的描(miao)(miao)述(shu)符。針(zhen)對cmd的值(zhi),fcntl能(neng)夠接受第三(san)個參數int arg。
[返回值]
fcntl()的返回(hui)值與命(ming)令(ling)有(you)關。如果出錯,所有(you)命(ming)令(ling)都返回(hui)-1,如果成功則(ze)返回(hui)某個其(qi)他(ta)值。下列(lie)三個命(ming)令(ling)有(you)特定(ding)返回(hui)值:F_DUPFD , F_GETFD , F_GETFL以(yi)及F_GETOWN。
F_DUPFD 返回新的文件(jian)描述符
F_GETFD 返回相應標志
F_GETFL , F_GETOWN 返(fan)回一個正的(de)進程(cheng)ID或(huo)負的(de)進程(cheng)組ID
fcntl函數有5種功能:
1. 復(fu)制一個現有的描(miao)述符(cmd=F_DUPFD).
2. 獲得(de)/設置文件描(miao)述(shu)符標記(cmd=F_GETFD或F_SETFD).
3. 獲得/設置文件狀(zhuang)態標記(cmd=F_GETFL或F_SETFL).
4. 獲得/設置異步I/O所有(you)權(cmd=F_GETOWN或F_SETOWN).
5. 獲得/設置記錄鎖(cmd=F_GETLK , F_SETLK或F_SETLKW).
1. cmd值的F_DUPFD :
F_DUPFD 返(fan)回一個如下描述(shu)的(文(wen)件)描述(shu)符:
● 小(xiao)的大于或(huo)等于arg的一個可(ke)用(yong)的描述符
● 與(yu)原(yuan)始(shi)操作符一樣的(de)某對象的(de)引用
● 如果對象是文件(file)的話,則返回(hui)一個(ge)新的描述符,這個(ge)描述符與arg共(gong)享相同的偏移量(offset)
● 相同的訪問(wen)模(mo)式(讀,寫或讀/寫)
● 相(xiang)同的文件(jian)狀態(tai)標志(如(ru):兩(liang)個文件(jian)描述符共享相(xiang)同的狀態(tai)標志)
● 與新的文(wen)件描述符結合在一起的close-on-exec標志(zhi)被設置(zhi)成交叉式(shi)訪問execve(2)的系統調用
實際上調(diao)用dup(oldfd);
等效于
fcntl(oldfd, F_DUPFD, 0);
而(er)調(diao)用dup2(oldfd, newfd);
等效于
close(oldfd);
fcntl(oldfd, F_DUPFD, newfd);
2. cmd值的F_GETFD和F_SETFD:
F_GETFD 取得與文(wen)(wen)(wen)件(jian)描述符(fu)fd聯合(he)的(de)close-on-exec標志,類似FD_CLOEXEC。如果(guo)(guo)返回值和FD_CLOEXEC進行與運算結(jie)果(guo)(guo)是0的(de)話,文(wen)(wen)(wen)件(jian)保持交叉式訪問(wen)exec(),否則(ze)如果(guo)(guo)通過(guo)exec運行的(de)話,文(wen)(wen)(wen)件(jian)將被(bei)關閉(bi)(arg 被(bei)忽(hu)略(lve))
F_SETFD 設(she)置close-on-exec標志,該標志以參數arg的FD_CLOEXEC位決定,應(ying)當了解很多現存的涉及文件描述(shu)符標志的程序并不使用(yong)常數 FD_CLOEXEC,而是將此標志設(she)置為0(系(xi)統默認,在exec時(shi)不關閉(bi))或1(在exec時(shi)關閉(bi))
在修改文(wen)件描述符標(biao)志或(huo)文(wen)件狀態標(biao)志時必須(xu)謹慎,先要(yao)取(qu)得現在的(de)標(biao)志值(zhi),然后按(an)照希望(wang)修改它(ta),后設置(zhi)新標(biao)志值(zhi)。不能只是執行F_SETFD或(huo)F_SETFL命(ming)令,這樣會關閉以前設置(zhi)的(de)標(biao)志位(wei)。
3. cmd值的F_GETFL和F_SETFL:
F_GETFL 取得fd的文(wen)件狀態標志,如同(tong)下面的描(miao)述一樣(arg被忽略),在說明open函數(shu)時,已說明
了文件狀態標(biao)志(zhi)(zhi)。不幸的(de)是(shi),三個存取方式(shi)標(biao)志(zhi)(zhi) (O_RDONLY , O_WRONLY , 以及O_RDWR)并(bing)不各占(zhan)1位。(這(zhe)(zhe)三種(zhong)標(biao)志(zhi)(zhi)的(de)值各是(shi)0 , 1和(he)2,由于歷史原(yuan)因,這(zhe)(zhe)三種(zhong)值互斥 — 一(yi)個文件只能(neng)有(you)這(zhe)(zhe)三種(zhong)值之(zhi)一(yi)。) 因此首先必須用屏(ping)蔽(bi)字O_ACCMODE相(xiang)與取得存取方式(shi)位,然后將結果(guo)與這(zhe)(zhe)三種(zhong)值相(xiang)比較。
F_SETFL 設置給arg描述符狀(zhuang)態標(biao)(biao)志(zhi),可以更(geng)改(gai)的幾個標(biao)(biao)志(zhi)是:O_APPEND,O_NONBLOCK,O_SYNC 和 O_ASYNC。而fcntl的文件(jian)狀(zhuang)態標(biao)(biao)志(zhi)總共有7個:O_RDONLY , O_WRONLY , O_RDWR , O_APPEND , O_NONBLOCK , O_SYNC和O_ASYNC
可更改的幾個標(biao)志(zhi)如下面的描述:
O_NONBLOCK 非阻塞I/O,如(ru)(ru)果read(2)調用沒有可讀(du)取的數(shu)據,或者如(ru)(ru)果write(2)操作將(jiang)阻塞,則read或write調用將(jiang)返回-1和EAGAIN錯(cuo)誤(wu)
O_APPEND 強制每次寫(write)操作都添加在文件大的末尾,相當于open(2)的O_APPEND標志
O_DIRECT 小(xiao)化(hua)(hua)或去掉reading和writing的(de)緩(huan)(huan)存(cun)影響。系統將企圖避免緩(huan)(huan)存(cun)你(ni)的(de)讀或寫的(de)數(shu)(shu)據(ju)。如果不能夠(gou)避免緩(huan)(huan)存(cun),那么它(ta)將小(xiao)化(hua)(hua)已經被緩(huan)(huan)存(cun)了的(de)數(shu)(shu)據(ju)造成的(de)影響。如果這個(ge)標志用(yong)的(de)不夠(gou)好(hao),將大大的(de)降低性能
O_ASYNC 當I/O可用的時(shi)候(hou),允許(xu)SIGIO信號(hao)發送到進程組,例如:當有數據可以讀的時(shi)候(hou)
4. cmd值的F_GETOWN和F_SETOWN: 【Linux公社 //www.linuxidc.com 】
F_GETOWN 取得當(dang)前正在(zai)接收(shou)SIGIO或者SIGURG信號(hao)的進程(cheng)(cheng)id或進程(cheng)(cheng)組id,進程(cheng)(cheng)組id返回的是負值(arg被忽略(lve))
F_SETOWN 設置將(jiang)接收SIGIO和(he)SIGURG信號(hao)的進程id或進程組(zu)id,進程組(zu)id通過提供(gong)負值的arg來說明(ming)(arg絕對值的一(yi)個進程組(zu)ID),否(fou)則arg將(jiang)被認為是(shi)進程id
5. cmd值的F_GETLK, F_SETLK或F_SETLKW: 獲(huo)得/設置記(ji)錄鎖的功能,成功則返(fan)回0,若有錯誤則返(fan)回-1,錯誤原因存(cun)于(yu)errno。
F_GETLK 通過(guo)第(di)(di)三個參數arg(一(yi)個指向flock的(de)(de)(de)結構(gou)體(ti))取得第(di)(di)一(yi)個阻塞lock description指向的(de)(de)(de)鎖(suo)。取得的(de)(de)(de)信(xin)(xin)息(xi)將(jiang)覆蓋傳到fcntl()的(de)(de)(de)flock結構(gou)的(de)(de)(de)信(xin)(xin)息(xi)。如(ru)果沒有發現能夠阻止本次鎖(suo)(flock)生(sheng)成的(de)(de)(de)鎖(suo),這(zhe)個結構(gou)將(jiang)不被改變,除非鎖(suo)的(de)(de)(de)類型被設(she)置(zhi)成F_UNLCK
F_SETLK 按照指(zhi)向(xiang)結構(gou)體flock的(de)指(zhi)針的(de)第三個(ge)參數arg所描(miao)述(shu)的(de)鎖(suo)的(de)信息設置(zhi)或(huo)者清除一個(ge)文(wen)件的(de)segment鎖(suo)。F_SETLK被(bei)用來(lai)實現共(gong)享(或(huo)讀)鎖(suo)(F_RDLCK)或(huo)獨占(zhan)(寫)鎖(suo)(F_WRLCK),同樣可以去(qu)掉(diao)這兩種鎖(suo)(F_UNLCK)。如果共(gong)享鎖(suo)或(huo)獨占(zhan)鎖(suo)不能被(bei)設置(zhi),fcntl()將(jiang)立即(ji)返回EAGAIN
F_SETLKW 除(chu)了(le)共(gong)享(xiang)鎖(suo)或(huo)獨占鎖(suo)被(bei)其他的(de)鎖(suo)阻塞這(zhe)(zhe)種情(qing)況外(wai),這(zhe)(zhe)個(ge)命(ming)令和F_SETLK是一樣的(de)。如果共(gong)享(xiang)鎖(suo)或(huo)獨占鎖(suo)被(bei)其他的(de)鎖(suo)阻塞,進程將等(deng)待(dai)直到這(zhe)(zhe)個(ge)請求能夠完成。當fcntl()正在(zai)等(deng)待(dai)文件的(de)某(mou)個(ge)區(qu)域的(de)時候捕捉到一個(ge)信(xin)號(hao)(hao),如果這(zhe)(zhe)個(ge)信(xin)號(hao)(hao)沒有被(bei)指定SA_RESTART, fcntl將被(bei)中斷
當一(yi)個(ge)共享(xiang)(xiang)(xiang)鎖(suo)被set到(dao)一(yi)個(ge)文件的(de)(de)(de)某(mou)段的(de)(de)(de)時候,其他的(de)(de)(de)進程(cheng)可以(yi)set共享(xiang)(xiang)(xiang)鎖(suo)到(dao)這(zhe)(zhe)(zhe)個(ge)段或這(zhe)(zhe)(zhe)個(ge)段的(de)(de)(de)一(yi)部(bu)分。共享(xiang)(xiang)(xiang)鎖(suo)阻(zu)止任何其他進程(cheng)set獨占鎖(suo)到(dao)這(zhe)(zhe)(zhe)段保護區域的(de)(de)(de)任何部(bu)分。如果文件描述符沒有以(yi)讀的(de)(de)(de)訪問方式打開的(de)(de)(de)話,共享(xiang)(xiang)(xiang)鎖(suo)的(de)(de)(de)設置請(qing)求會失(shi)敗。
獨(du)占鎖(suo)阻止任何(he)其他的進程在這段保(bao)護(hu)區域(yu)任何(he)位置(zhi)設置(zhi)共(gong)享鎖(suo)或(huo)獨(du)占鎖(suo)。如果文件描述符不(bu)是以寫的訪問方式(shi)打(da)開(kai)的話,獨(du)占鎖(suo)的請(qing)求會失敗。
結構體flock的指針:
struct flcok
{
short int l_type; /* 鎖定(ding)的狀態(tai)*/
//以下的三個(ge)參數用(yong)于(yu)分(fen)段對文件(jian)加鎖,若對整(zheng)個(ge)文件(jian)加鎖,則:l_whence=SEEK_SET, l_start=0, l_len=0
short int l_whence; /*決(jue)定l_start位置(zhi)*/
off_t l_start; /*鎖定(ding)區域的開頭(tou)位置(zhi)*/
off_t l_len; /*鎖定區域的大小(xiao)*/
pid_t l_pid; /*鎖定動作的進程*/
};
l_type 有三種狀態:
F_RDLCK 建立一(yi)個供讀取用的鎖定
F_WRLCK 建(jian)立一個供寫入用的鎖定(ding)
F_UNLCK 刪除之前建立(li)的鎖定
l_whence 也有三種方式:
SEEK_SET 以文(wen)件開頭為鎖定(ding)的(de)起始位(wei)置
SEEK_CUR 以(yi)目(mu)前文件讀(du)寫位置為(wei)鎖(suo)定的起始位置
SEEK_END 以文件結尾為鎖定的(de)起始位置
fcntl文件鎖有兩種類型:建議性鎖和強制性鎖
建議性鎖是這樣規定的:每(mei)個使用上(shang)鎖文件的進程都要檢查是否有(you)鎖存在,當然還得尊重(zhong)已有(you)的鎖。內核和系統總體上(shang)都堅持(chi)不(bu)使用建議性(xing)鎖,它(ta)們(men)依靠(kao)程序員遵守(shou)這個規定(ding)。
強制性鎖是由內核執行的:當文(wen)件(jian)(jian)被上鎖來(lai)進(jin)(jin)行寫入操(cao)作時,在(zai)鎖定(ding)該(gai)文(wen)件(jian)(jian)的進(jin)(jin)程釋(shi)放該(gai)鎖之前,內核會阻止任何(he)對該(gai)文(wen)件(jian)(jian)的讀或(huo)寫訪問,每次(ci)讀或(huo)寫訪問都得(de)檢(jian)查鎖是否存在(zai)。

