一、 文件锁用于多个用户共同使用或操作同一个文件。有读锁的时候可以再加读锁,不能再加写锁。有写锁的时候,不能加任何锁,加读锁时,该描述符必须是读打开,加写锁时,该描述符必须是写打开, 且只在进程间有用。
使用flock(锁定文件或解除锁定)函数
头文件 #include<sys/file.h> 定义函数 int flock(int fd,int operation); 函数说明 flock()会依参数operation所指定的方式对参数fd所指的文件做各种锁定或解除锁定的动作。此函数只能锁定整个文件,无法锁定文件的某一区域。 参数 operation有下列四种情况: LOCK_SH 建立共享锁定。多个进程可同时对同一个文件作共享锁定。 LOCK_EX 建立互斥锁定。一个文件同时只有一个互斥锁定。 LOCK_UN 解除文件锁定状态。 LOCK_NB 无法建立锁定时,此操作可不被阻断,马上返回进程。通常与LOCK_SH或LOCK_EX 做OR(|)组合。 单一文件无法同时建立共享锁定和互斥锁定,而当使用dup()或fork()时文件描述词不会继承此种锁定。 返回值 返回0表示成功,若有错误则返回-1,错误代码存于errno。
上锁方法:
#include int lock_set(int fd, int type) { struct flock lock; lock.l_type = type; lock.l_start = 0; lock.l_whence = SEEK_SET; lock.l_len = 0; lock.l_pid = -1; fcntl(fd, F_GETLK, &lock); if(lock.l_type != F_UNLCK) { if(lock.l_type == F_RDLCK) { printf("Read lock already set by %d\n", lock.l_pid); } else if(lock.l_type == F_WRLCK) { printf("Write lock already set by %d\n", lock.l_pid); } } lock.l_type = type; if(fcntl(fd, F_SETLKW, &lock) < 0) { printf("lock failed :type = %d\n", lock.l_type); } switch(lock.l_type) { case F_RDLCK: printf("read lock set by %d\n", getpid()); break; case F_WRLCK: printf("write lock set by %d\n", getpid()); break; case F_UNLCK: printf("UN lock set by %d\n", getpid()); break; default: break; } }
上写锁:
#include #include #include #include #include "set_lock.h" int main() { int fd; fd = open("readme", O_RDWR | O_CREAT, 0666); if(fd < 0) { printf("Open file error\n"); exit(1); } lock_set(fd, F_WRLCK); getchar(); lock_set(fd, F_UNLCK); getchar(); return 0; } 上读锁: #include #include #include #include #include "set_lock.h" int main() { int fd; fd = open("readme", O_RDWR | O_CREAT, 0666); if(fd < 0) { printf("Open file error\n"); exit(1); } lock_set(fd, F_RDLCK); getchar(); lock_set(fd, F_UNLCK); getchar(); return 0; } 在两个终端上进行测试。 二、多路复用: select 、 poll select: #include #include #include #include #define MAX(a, b) ((a) > (b) ? (a) : (b)) int main() { int fd[3]; char buf[1024]; int res; int max_fd; int i; int num; fd_set insert; fd_set temp_insert; struct timeval tv; fd[0] = 0; if(fd[1] = open("in1", O_RDONLY | O_NONBLOCK) < 0) { printf("open in1 error!\n"); return 1; } if(fd[2] = open("in2", O_RDONLY | O_NONBLOCK) < 0) { printf("open in2 error!\n"); return 1; } max_fd = MAX(MAX(fd[0], fd[1]), fd[2]); FD_ZERO(&insert); for(i = 0; i < 3; i++) { FD_SET(fd[i], &insert); } tv.tv_sec = 60; tv.tv_usec = 0; while(FD_ISSET(fd[0], &insert) || FD_ISSET(fd[1], &insert) || FD_ISSET(fd[2], &insert)) { temp_insert = insert; res = select(max_fd + 1, &temp_insert, NULL, NULL, &tv); switch(res) { case -1: printf("select error\n"); return 1; break; case 0: printf("time out\n"); return 1; break; default: for(i = 0; i < 3; i++) { if(FD_ISSET(fd[i], &temp_insert)) { memset(buf, 0, 1024); num = read(fd[i], buf, 1024); if(num < 0) { return 1; } else if(num == 0) { close(fd[i]); FD_CLR(fd[i], &insert); } else { if(i == 0) { if(buf[0] == 'q' || buf[0] == 'Q') { return 0; } } write(STDOUT_FILENO, buf, num); } } } } } } poll: #include #include #include #include #include #define BUF_SZ 1024 #define IO_IN_FILE 3 #define TIMEDELAY 60000 int main() { struct pollfd fd[IO_IN_FILE]; char buf[BUF_SZ]; int res; int real_read; int i; fd[0].fd = 0; if(fd[1].fd = open("in1", O_RDONLY | O_NONBLOCK) < 0) { printf("open in1 error!\n"); return 1; } if(fd[2].fd = open("in2", O_RDONLY | O_NONBLOCK) < 0) { printf("open in2 error!\n"); return 1; } for(i = 0; i < IO_IN_FILE; i++) { fd[i].events = POLLIN; } while(fd[0].events || fd[1].events || fd[2].events) { res = poll(fd, IO_IN_FILE, TIMEDELAY); switch(res) { case -1: printf("poll error\n"); return 1; break; case 0: printf("time out\n"); return 1; break; default: for(i = 0; i < IO_IN_FILE; i++) { if(fd[i].events) { memset(buf, 0, BUF_SZ); real_read = read(fd[i].fd, buf, BUF_SZ); if(real_read < 0) { printf("read error\n"); return 1; } else if(real_read == 0) { close(fd[i].fd); fd[i].events = 0; } else { if(i == 0) { if(buf[0] == 'q' || buf[0] == 'Q') { return 0; } } write(STDOUT_FILENO, buf, real_read); } } } } } return 0; }