分类:
2008-11-07 16:20:41
#include "apue.h"
#include
static void
lockabyte(const char *name, int fd, off_t offset)
{
if (writew_lock(fd, offset, SEEK_SET, 1) < 0)
err_sys("%s: writew_lock error", name);
printf("%s: got the lock, byte %ld\n", name, offset);
}
int
main(void)
{
int fd;
pid_t pid;
/*
* Create a file and write two bytes to it.
*/
if ((fd = creat("templock", FILE_MODE)) < 0)
err_sys("creat error");
if (write(fd, "ab", 2) != 2)
err_sys("write error");
TELL_WAIT();
if ((pid = fork()) < 0) {
err_sys("fork error");
} else if (pid == 0) { /* child */
lockabyte("child", fd, 0);
TELL_PARENT(getppid());
WAIT_PARENT();
lockabyte("child", fd, 1);
} else { /* parent */
lockabyte("parent", fd, 1);
TELL_CHILD(pid);
WAIT_CHILD();
lockabyte("parent", fd, 0);
}
exit(0);
}
5. 一个process里,一个文件的某一个descriptor(注意在一个process里,
有可能有多个descriptor对应同一个文件,如通过dup,dup2或者多次open)被关闭,那么该进程针对该文件
的所有的lock都会被释放,而不管究竟这些lock当初建立的时候是使用了那个descriptor。因为kernel纪录
文检锁的方法是在v-node里建立一个lock-list,每个list-item记载的只有进程id,以及区域和锁类型,没有纪录
descriptor。
可见,process table entry里记载了file descriptor,并且指向了对应的file table entry,dup调用会产生
新的descriptor,但是他们共同指向相同的file table entry。 再次open同一个文件会产生新的descriptor和新的
file table entry,但是他们和以前的file table entry最终指向了同一个v-node。即他们还是指向同一个文件。那么
此时,只要有一个descriptor被关闭,那么该文件上所有的lock都被remove。
6. 由5知道,当程序退出的时候,所有descriptor关闭,那么锁会自动释放。
7. 子进程会继承父进程的descriptor以及,并且与父进程指向相同的file table entry,但是子进程不会继承父进程
的lock,因为这样就乱了。那么如果子进程要想加锁,就得自己从新来过,而且子进程关闭该descriptor不会影响夫进程
里面的锁。
8. 进程执行exec时,会保留descriptor,从而也保留文件锁,但是前提是该descriptor没有被设置close-on-exec标记,因为
这个标记会使该文件在进程调用exec时被关闭,从而其上的锁也会被释放。
9. advisory and mandatory locking
所谓advisory的意思是说我们的程序,如果你们都是用锁机制,那么好一且正常,如果有些家或不用锁机制,直接读写
文件,那么我们也拿他没办法,文件会被弄坏。没有办法。
所谓mandatory意思是说,好了,我们现在有办法了,就算你不才用锁机制直接读写,我也会首先作出检查,看是否
有别的进程已经加了锁,如果是,那么好了你能否成功操作就要一举一定的rule了,这就是强制性的机制。
当然这建立在对open, read, write等函数的检查的基础上。但是有的实现,绕开了这些函数,而使用了unlink,尽管
该文件被加了读锁,但是人家虽然不能直接写,人家可以读出你的内容,然后对你unlink,然后人家新生成一个别的名字的文件,写完后,
等你加锁的进程完了,你这个文件也自动被remove了(前提是unlink将其最后一个link去掉了),人间再将新文件rename
成这个文件,也达到了同样的效果。
#include |
Returns: depends on cmd if OK (see following), 1 on error |
F_GETLK |
Determine whether the lock described by flockptr is blocked by some other lock. If a lock exists that would prevent ours from being created, the information on that existing lock overwrites the information pointed to by flockptr. If no lock exists that would prevent ours from being created, the structure pointed to by flockptr is left unchanged except for the l_type member, which is set to F_UNLCK. |
F_SETLK |
Set the lock described by flockptr. If we are trying to obtain a read lock (l_type of F_RDLCK) or a write lock (l_type of F_WRLCK) and the compatibility rule prevents the system from giving us the lock (), fcntl returns immediately with errno set to either EACCES or EAGAIN.
This command is also used to clear the lock described by flockptr (l_type of F_UNLCK). |
F_SETLKW |
This command is a blocking version of F_SETLK. (The W in the command name means wait.) If the requested read lock or write lock cannot be granted because another process currently has some part of the requested region locked, the calling process is put to sleep. The process wakes up either when the lock becomes available or when interrupted by a signal. |