《UNIX网络编程:卷2》P155-P156:图9-2
fcntl上锁的加1测试
--------------------------------------------
/* * lockmain.c * 图9-2 文件上锁例子的main函数 */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) #define MAXLINE 1024 #define SEQFILE "seqno" void my_lock(int fd); void my_unlock(int fd); int main(int argc, char *argv[]) { int fd; long i, seqno; pid_t pid; ssize_t n; char line[MAXLINE + 1]; pid = getpid(); // 获取进程ID // 打开文件 if ((fd = open(SEQFILE, O_RDWR, FILE_MODE)) < 0) { fprintf(stderr, "open %s error: %s\n", SEQFILE, strerror(errno)); exit(1); } for (i = 0; i < 20; i++) { my_lock(fd); // 锁定文件 lseek(fd, 0L, SEEK_SET); //定位到文件开始位置 if ((n = read(fd, line, MAXLINE)) < 0) { // 读取一行 fprintf(stderr, "read error: %s\n", strerror(errno)); exit(1); } line[n] = '\0'; n = sscanf(line, "%ld\n", &seqno); // 将字符转换成数字 printf("%s: pid = %d, seq# = %ld\n", argv[0], pid, seqno); seqno++; // 加1 snprintf(line, sizeof(line), "%ld\n", seqno); // 将数字写回缓冲区 lseek(fd, 0L, SEEK_SET); // 定位到文件开始处 if (write(fd, line, strlen(line)) < 0) { // 将缓冲区内容写回文件 fprintf(stderr, "write error: %s\n", strerror(errno)); exit(1); } my_unlock(fd); // 解锁文件 } exit(0); } /* * lockfcntl.c * P161 图9-3 fcntl上锁 */ void my_lock(int fd) { 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_SETLKW, &lock) < 0) { fprintf(stderr, "fcntl error: %s\n", strerror(errno)); } return; // 不做任何事情,直接返回 } void my_unlock(int fd) { struct flock lock; lock.l_type = F_UNLCK; // 解锁 lock.l_whence = SEEK_SET; lock.l_start = 0; lock.l_len = 0; // 解锁整个文件 if (fcntl(fd, F_SETLK, &lock) < 0) { fprintf(stderr, "fcntl error: %s\n", strerror(errno)); } return; // 不做任何事情,直接返回 }
--------------------------------------------
创建文件seqno,并写入1。运行程序:
$ ./lockmain & ./lockmain & [1] 2513 [2] 2514 $ ./lockmain: pid = 2513, seq# = 1 ./lockmain: pid = 2513, seq# = 2 ./lockmain: pid = 2513, seq# = 3 ./lockmain: pid = 2513, seq# = 4 ./lockmain: pid = 2513, seq# = 5 ./lockmain: pid = 2513, seq# = 6 ./lockmain: pid = 2513, seq# = 7 ./lockmain: pid = 2513, seq# = 8 ./lockmain: pid = 2513, seq# = 9 ./lockmain: pid = 2513, seq# = 10 ./lockmain: pid = 2513, seq# = 11 ./lockmain: pid = 2513, seq# = 12 ./lockmain: pid = 2513, seq# = 13 ./lockmain: pid = 2513, seq# = 14 ./lockmain: pid = 2513, seq# = 15 ./lockmain: pid = 2513, seq# = 16 ./lockmain: pid = 2513, seq# = 17 ./lockmain: pid = 2513, seq# = 18 ./lockmain: pid = 2513, seq# = 19 ./lockmain: pid = 2513, seq# = 20 ./lockmain: pid = 2514, seq# = 21 ./lockmain: pid = 2514, seq# = 22 ./lockmain: pid = 2514, seq# = 23 ./lockmain: pid = 2514, seq# = 24 ./lockmain: pid = 2514, seq# = 25 ./lockmain: pid = 2514, seq# = 26 ./lockmain: pid = 2514, seq# = 27 ./lockmain: pid = 2514, seq# = 28 ./lockmain: pid = 2514, seq# = 29 ./lockmain: pid = 2514, seq# = 30 ./lockmain: pid = 2514, seq# = 31 ./lockmain: pid = 2514, seq# = 32 ./lockmain: pid = 2514, seq# = 33 ./lockmain: pid = 2514, seq# = 34 ./lockmain: pid = 2514, seq# = 35 ./lockmain: pid = 2514, seq# = 36 ./lockmain: pid = 2514, seq# = 37 ./lockmain: pid = 2514, seq# = 38 ./lockmain: pid = 2514, seq# = 39 ./lockmain: pid = 2514, seq# = 40 [1]- 完成 ./lockmain [2]+ 完成 ./lockmain
该运行结果看上去是正确的,但这不足以告诉我们程序是否正常工作。只循环20次,两个进程中途不进行切换,我们可能永远也发现不了错误。需要更多循环次数的测试。