fcntl可實現對指定文件描述符的各種操作,其函數原型如下:
int fcntl(int fd, int cmd, ... /* arg */ );
其中,操作類型由cmd決定。cmd可取如下值:
- F_DUPFD:復制文件描述符
- F_DUPFD_CLOEXEC:復制文件描述符,新文件描述符被設置了close-on-exec
- F_GETFD:讀取文件描述標識
- F_SETFD:設置文件描述標識
- F_GETFL:讀取文件狀態標識
- F_SETFL:設置文件狀態標識
- F_GETLK:如果已經被加鎖,返回該鎖的數據結構。如果沒有被加鎖,將l_type設置為F_UNLCK
- F_SETLK:給文件加上進程鎖
- F_SETLKW:給文件加上進程鎖,如果此文件之前已經被加了鎖,則一直等待鎖被釋放。
接下來看兩段代碼:
#include <fcntl.h> #include <unistd.h> #include <cstring> #include <cstdio> #include <cstdlib> #define ERR_EXIT(msg) \ do \ { \ perror(msg); \ exit(-1); \ } while(0) int main() { int fd = open("test.dat", O_CREAT | O_RDWR | O_TRUNC, 0644); if (fd < 0) ERR_EXIT("open file failed"); struct flock f; memset(&f, 0, sizeof(f)); f.l_type = F_WRLCK; f.l_whence = SEEK_SET; f.l_start = 0; f.l_len = 0; if (fcntl(fd, F_SETLK, &f) < 0) ERR_EXIT("lock file failed"); printf("press any key to unlock\n"); getchar(); f.l_type = F_UNLCK; if (fcntl(fd, F_SETLK, &f) < 0) ERR_EXIT("unlock file failed"); return 0; }
上述代碼實現了加鎖和解鎖兩個操作。
#include <unistd.h> #include <fcntl.h> #include <cstdio> #include <cstdlib> #include <cerrno> #include <sys/types.h> #include <sys/stat.h> #define ERR_EXIT(msg) \ do \ { \ perror(msg); \ exit(-1); \ } while(0) void set_flag(int fd, int flags); void clr_flag(int fd, int flags); int main() { char buf[1024]; set_flag(0, O_NONBLOCK); int ret = read(0, buf, 1024); if (ret < 0) ERR_EXIT("read failed"); return 0; } void set_flag(int fd, int flags) { int val = fcntl(fd, F_GETFL, 0); if (val < 0) ERR_EXIT("get flag failed"); val |= flags; if (fcntl(fd, F_SETFL, val) < 0) ERR_EXIT("set flag failed"); } void clr_flag(int fd, int flags) { int val = fcntl(fd, F_GETFL, 0); if (val < 0) ERR_EXIT("get flag failed"); val &= ~flags; if (fcntl(fd, F_SETFL, val) < 0) ERR_EXIT("set flag failed"); }
其中set_flag設置文件狀態標識,clr_flag清除文件狀態標識。main函數中將stdout設置成非阻塞,所以執行read時,不等待用戶輸入而直接返回錯誤。
