这个程序首先声明了一个类型为 struct flock 的变量,它代表一个锁,并对它的 5 个域做了初始化。第一个初始化
lock.l_type = F_WRLCK; /* exclusive lock */
使得这个锁为排斥锁(read-write)而不是一个共享锁(read-only)。假如生产者获得了这个锁,则其他的进程将不能够对文件做读或者写操作,直到生产者释放了这个锁,或者显式地调用 fcntl ,又或者隐式地关闭这个文件。(当进程终止时,所有被它打开的文件都会被自动关闭,从而释放了锁)
上面的程序接着初始化其他的域。主要的效果是整个文件都将被锁上。但是,有关锁的 API 允许特别指定的字节被上锁。例如,假如文件包含多个文本记录,则单个记录(或者甚至一个记录的一部分)可以被锁,而其余部分不被锁。
第一次调用 fcntl
if (fcntl(fd, F_SETLK, &lock) < 0)
尝试排斥性地将文件锁住,并检查调用是否成功。一般来说, fcntl 函数返回 -1 (因此小于 0)意味着失败。第二个参数 F_SETLK 意味着 fcntl 的调用不是堵塞的;函数立即做返回,要么获得锁,要么显示失败了。假如替换地使用 F_SETLKW (末尾的 W 代指等待),那么对 fcntl 的调用将是阻塞的,直到有可能获得锁的时候。在调用 fcntl 函数时,它的第一个参数 fd 指的是文件描述符,第二个参数指定了将要采取的动作(在这个例子中,F_SETLK 指代设置锁),第三个参数为锁结构的地址(在本例中,指的是 &lock )。
假如生产者获得了锁,这个程序将向文件写入两个文本记录。
在向文件写入内容后,生产者改变锁结构中的 l_type 域为 unlock 值:
lock.l_type = F_UNLCK;
并调用 fcntl 来执行解锁操作。最后程序关闭了文件并退出。
示例 2. 消费者程序
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> -
#define FileName "data.dat" -
void report_and_exit(const char* msg) { [perror][4](msg); [exit][5](-1); /* EXIT_FAILURE */ } -
int main() { struct flock lock; lock.l_type = F_WRLCK; /* read/write (exclusive) lock */ lock.l_whence = SEEK_SET; /* base for seek offsets */ lock.l_start = 0; /* 1st byte in file */ lock.l_len = 0; /* 0 here means 'until EOF' */ lock.l_pid = getpid(); /* process id */ -
int fd; /* file descriptor to identify a file within a process */ if ((fd = open(FileName, O_RDONLY)) < 0) /* -1 signals an error */ report_and_exit("open to read failed..."); -
/* If the file is write-locked, we can't continue. */ fcntl(fd, F_GETLK, &lock); /* sets lock.l_type to F_UNLCK if no write lock */ if (lock.l_type != F_UNLCK) report_and_exit("file is still write locked..."); -
lock.l_type = F_RDLCK; /* prevents any writing during the reading */ if (fcntl(fd, F_SETLK, &lock) < 0) report_and_exit("can't get a read-only lock..."); -
/* Read the bytes (they happen to be ASCII codes) one at a time. */ int c; /* buffer for read bytes */ while (read(fd, &c, 1) > 0) /* 0 signals EOF */ write(STDOUT_FILENO, &c, 1); /* write one byte to the standard output */ -
/* Release the lock explicitly. */ lock.l_type = F_UNLCK; if (fcntl(fd, F_SETLK, &lock) < 0) report_and_exit("explicit unlocking failed..."); -
close(fd); return 0; }
(编辑:ASP站长网)
|