文件I/O实践(3) --文件共享与fcntl
文件共享
一個進程打開了兩個文件
文件表條目(file-table-entry):
? ?1.文件狀態標志(file-status-flags):?讀/寫/追加/同步/非阻塞等;
? ?2.當前文件偏移量
? ?3.v節點指針
兩個獨立的進程打開同一個文件
復制文件描述符
?
方法有三種:
1.dup
2.dup2?
#include <unistd.h> int dup(int oldfd); int dup2(int oldfd, int newfd); //示例 int main(int argc, char *argv[]) {int fd = open("text.txt", O_WRONLY|O_TRUNC);if (fd == -1)err_exit("open O_WRONLY error");// close(1); //將標準輸出關閉, 則文件描述符1將空閑 // int dupfd = dup(fd);int dupfd = dup2(fd, 1);cout << "dupfd = " << dupfd << endl; } /** 示例: 實現文件拷貝 其中execlp會在后面介紹 **/ int main(int argc, char *argv[]) {if (argc < 3)err_quit("usage: ./main file-name1 file-name2");close(STDIN_FILENO);open(argv[1], O_RDONLY);close(STDOUT_FILENO);open(argv[2], O_WRONLY|O_CREAT, 0666);execlp("/bin/cat", "cat", NULL);err_exit("execlp error"); } 3.fcntlint fcntl(int fd, F_DUPFD, ... /* arg */ ); //示例見下
fcntl
#include <unistd.h> #include <fcntl.h> int fcntl(int fd, int cmd, ... /* arg */ );? 操縱文件描述符,?改變已經打開的文件的屬性
fcntl常用操作(cmd常用取值) | |
F_DUPFD?(long) | 復制文件描述符 ? |
F_GETFD?(void) F_SETFD?(long) | 文件描述符標志 ? |
F_GETFL?(void) F_SETFL?(long) | 文件狀態標志 ? |
F_GETLK F_SETLK,F_SETLKW(阻塞) | 文件鎖 |
文件狀態標志
F_GETFL?(void)
?Get?the?file?access?mode?and?the?file?status?flags;?arg?is?ignored.
F_SETFL?(int)
?Set?the?file?status?flags?to??the??value??specified??by??arg.???File??access??mode(O_RDONLY,??O_WRONLY,??O_RDWR)??and??file??creation??flags?(i.e.,?O_CREAT,?O_EXCL,?O_NOCTTY,?O_TRUNC)?in?arg?are?ignored.??On?Linux?this?command?can?change?only??the?O_APPEND,?O_ASYNC,?O_DIRECT,?O_NOATIME,?and?O_NONBLOCK?flags.
//示例: 給文件描述符0設置成非阻塞模式 int main(int argc, char *argv[]) {int flags = fcntl(0, F_GETFL, 0);if (flags == -1)err_exit("fcntl get error");flags |= O_NONBLOCK;if (fcntl(0, F_SETFL, flags) == -1)err_exit("fcntl set error");char buf[BUFSIZ];if (read(0, buf, sizeof(buf)) == -1)err_exit("read STDIN_FILENO error");cout << "buffer size = " << strlen(buf) << endl;cout << buf << endl; } //示例: 文件狀態設置與清除(函數封裝) void set_fl(int fd, int setFlag) {int flags = fcntl(fd, F_GETFL, 0);if (flags == -1)err_exit("fcntl get flags error");//設置狀態flags |= setFlag;if (fcntl(fd, F_SETFL, flags) == -1)err_exit("fcntl set flags error"); } void clr_fl(int fd, int clrFlag) {int flags = fcntl(fd, F_GETFL, 0);if (flags == -1)err_exit("fcntl get flags error");//清除狀態flags &= ~clrFlag;if (fcntl(fd, F_SETFL, flags) == -1)err_exit("fcntl set flags error"); }//測試 int main(int argc, char *argv[]) {set_fl(0, O_NONBLOCK);clr_fl(0, O_NONBLOCK);char buf[BUFSIZ];if (read(0, buf, sizeof(buf)) == -1)err_exit("read STDIN_FILENO error");cout << "buffer size = " << strlen(buf) << endl;cout << buf << endl; }文件鎖
F_SETLK?(struct?flock?*)
?Acquire??a?lock?(when?l_type?is?F_RDLCK?or?F_WRLCK)?or?release?a?lock?(when?l_type?is?F_UNLCK)?on?the?bytes?specified?by?the?l_whence,?l_start,?and?l_len??fields??of?lock.???If?a?conflicting?lock?is?held?by?another?process,?this?call?returns?-1?and?sets?errno?to?EACCES?or?EAGAIN.
F_SETLKW?(struct?flock?*) 如果加鎖不成功:會一直阻塞直到解鎖
?As?for?F_SETLK,?but?if?a?conflicting?lock?is?held?on?the?file,?then?wait?for??that?lock?to?be?released.??If?a?signal?is?caught?while?waiting,?then?the?call?is?interrupted?and?(after?the?signal??handler??has??returned)??returns??immediately??(with?return?value?-1?and?errno?set?to?EINTR;?see?signal(7)).
F_GETLK?(struct?flock?*)
?On??input??to?this?call,?lock?describes?a?lock?we?would?like?to?place?on?the?file.
?If?the?lock?could?be?placed,?fcntl()?does??not??actually??place??it,??but??returns?F_UNLCK??in??the?l_type?field?of?lock?and?leaves?the?other?fields?of?the?structure?unchanged.??If?one?or?more??incompatible??locks??would??prevent??this??lock??being?placed,??then??fcntl()??returns??details??about??one?of?these?locks?in?the?l_type,?l_whence,?l_start,?and?l_len?fields?of?lock?and?sets?l_pid?to?be?the??PID??of??the?process?holding?that?lock.
//文件鎖結構體 struct flock {...short l_type; /* Type of lock: F_RDLCK,F_WRLCK, F_UNLCK */short l_whence; /* How to interpret l_start:SEEK_SET, SEEK_CUR, SEEK_END */off_t l_start; /* Starting offset for lock */off_t l_len; /* Number of bytes to lock */pid_t l_pid; /* PID of process blocking our lock(F_GETLK only) */... };注意:?Specifying?0?for?l_len?has?the?special?meaning:?lock?all?bytes?starting??at??
the??location??specified??by?l_whence?and?l_start?through?to?the?end?of?file,?
no?matter?how?large?the?file?grows.
//示例1 int main(int argc, char *argv[]) {int fd = open("test.txt", O_RDWR|O_CREAT|O_TRUNC, 0666);if (fd == -1)err_exit("open file error");struct flock lock;lock.l_type = F_WRLCK; //設定獨占鎖lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0; //鎖定全部文件//if (fcntl(fd, F_SETLK, &lock) == 0) //對比下面if (fcntl(fd, F_SETLKW, &lock) == 0){cout << "file lock success, press any key to unlock..." << endl;cin.get();lock.l_type = F_UNLCK;lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0;if (fcntl(fd, F_SETLK, &lock) == -1)err_exit("file unlock error");elsecout << "file unlock success" << endl;}elseerr_exit("file lock error"); } //示例2: 打印加鎖進程號 int main(int argc, char *argv[]) {int fd = open("test.txt", O_RDWR|O_CREAT|O_TRUNC, 0666);if (fd == -1)err_exit("open file error");struct flock lock;lock.l_type = F_WRLCK; //設定獨占鎖lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0; //鎖定全部文件if (fcntl(fd, F_SETLK, &lock) == 0){cout << "file lock success, press any key to unlock..." << endl;cin.get();lock.l_type = F_UNLCK;lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0;if (fcntl(fd, F_SETLK, &lock) == -1)err_exit("file unlock error");elsecout << "file unlock success" << endl;}else //如果失敗, 則獲取鎖信息{if (fcntl(fd, F_GETLK, &lock) == -1)err_exit("get lock error");cout << "lock process: " << lock.l_pid << endl;if (lock.l_type == F_WRLCK)cout << "type: F_WRLCK" << endl;elsecout << "type: F_RDLCK" << endl;if (lock.l_whence == SEEK_SET)cout << "whence: SEEK_SET" << endl;else if (lock.l_whence == SEEK_END)cout << "whence: SEEK_END" << endl;elsecout << "whence: SEEK_CUR" << endl;} }
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!
總結
以上是生活随笔為你收集整理的文件I/O实践(3) --文件共享与fcntl的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: QOS 的基本概念
- 下一篇: 导入代码时eclipse的src目录变为