fcntl系统调用
fcntl系统调用
例1: 文件的状态标志
myfcntl_access.c
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <errno.h> #define ERROR(flag) \ if(flag) \ { \ printf("%d: ",__LINE__); \ fflush(stdout); \ perror("error"); \ exit(errno); \ } int main(int argc,char *argv[]) { int ret; int access_mode; int fd; fd = open(argv[1], O_RDWR ); ERROR(fd == -1); ret = fcntl(fd, F_SETFL, O_APPEND | O_NONBLOCK); ERROR(ret < 0); ret = fcntl(fd, F_GETFL,0); ERROR(ret < 0); access_mode = ret & O_ACCMODE; if (access_mode == O_RDONLY) { printf("%s: read only",argv[1]); } else if (access_mode == O_WRONLY) { printf("%s: write only",argv[1]); } else if (access_mode == O_RDWR) { printf("%s: read + write",argv[1]); } if (ret & O_APPEND) { printf(", append"); } if (ret & O_NONBLOCK) { printf(", nonblock"); } printf("\n"); return 0; }
编译链接执行, 结果输出文件的属性如下:
例2: 对文件描述符设置读写锁
myfcntl_lock.c
#include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include <stdlib.h> #include <errno.h> #include <string.h> #define ERROR(flag) \ if(flag) \ { \ printf("%d: ",__LINE__); \ fflush(stdout); \ perror("error"); \ exit(errno); \ } int lock_set(int fd, struct flock * lock) { if (fcntl(fd, F_SETLK, lock) == 0) { if (lock->l_type == F_RDLCK) { printf("set read lock, pid:%d\n", getpid()); } else if (lock->l_type == F_WRLCK) { printf("set write lock, pid:%d\n", getpid()); } else if (lock->l_type == F_UNLCK) { printf("release lock, pid:%d\n", getpid()); } } else { perror("lock operation fail\n"); return -1; } return 0; } int lock_test(int fd, struct flock * lock) { if (fcntl(fd, F_GETLK, lock) == 0) { if (lock->l_type == F_UNLCK) { printf("lock can be set in fd\n"); return 0; } else { if (lock->l_type == F_RDLCK) { printf("can't set lock, read lock has been set by: %d\n", lock->l_pid); } else if (lock->l_type == F_WRLCK) { printf("can't set lock, write lock has been set by: %d\n", lock->l_pid); } return -2; } } else { perror("get incompatible locks fail"); return -1; } } int main(int argc,char *argv[1]) { int fd; int ret; struct flock lock; char read_buf[32]; fd = open(argv[1], O_CREAT | O_TRUNC | O_RDWR, S_IRWXU); ERROR(fd == -1); ret = write(fd, "=====hello 123456789=====", 25); ERROR(ret != 25); memset(&lock, 0, sizeof (struct flock)); lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; lock.l_type = F_RDLCK; if (lock_test(fd, &lock) == 0) { lock.l_type = F_RDLCK; lock_set(fd, &lock); } lseek(fd, 0, SEEK_SET); ret = read(fd, read_buf, 25); ERROR(ret < 0); read_buf[ret] = '\0'; printf("%s\n", read_buf); getchar(); lock.l_type = F_WRLCK; if (lock_test(fd, &lock) == 0) { lock.l_type = F_WRLCK; lock_set(fd, &lock); } getchar();
lock.l_type = F_UNLCK; lock_set(fd, &lock); close(fd); return 0; }
编译链接运行, 有如下输出结果:
结果1: 只在一个终端执行, 对打开文件的描述符加读锁, 写锁及解锁结果如下图:
结果2: 两个终端同时执行同样的命令, 再先后按回车键, 对打开的文件描述符加读锁,写锁及解锁, 输出结果如下:
理解如下:
1. 此文件读写锁没有强制性(提供机制, 由接口使用者实现策略).
2. 不同进程对同一打开的文件描述符可以同时加读锁
3. 对已加读锁的文件描述符, 不能再加写锁
结果3: 两个终端同时执行同样的命令, 其中一个先连续按两次回车, 使其对文件描述符加写锁, 如下:
理解如下:
对已加写锁的文件,不能加读锁, 也不能加写锁