3. 锁继承与释放的语义
  flock()根据调用时operation参数传入LOCK_UN的值来释放一个文件锁。此外,锁会在相应的文件描述符被关闭之后自动释放。同时,当一个文件描述符被复制时(dup()、dup2()、或一个fcntl() F_DUPFD操作),新的文件描述符会引用同一个文件锁。
  flock(fd, LOCK_EX);
  new_fd = dup(fd);
  flock(new_fd, LOCK_UN);
  这段代码先在fd上设置一个互斥锁,然后通过fd创建一个指向相同文件的新文件描述符new_fd,后通过new_fd来解锁。从而我们可以得知新的文件描述符指向了同一个锁。所以,如果通过一个特定的文件描述符获取了一个锁并且创建了该描述符的一个或多个副本,那么,如果不显示的调用一个解锁操作,只有当文件描述符副本都被关闭了之后锁才会被释放。
  由上我们可以推出,如果使用fork()创建一个子进程,子进程会复制父进程中的所有描述符,从而使得它们也会指向同一个文件锁。例如下面的代码会导致一个子进程删除一个父进程的锁:
  flock (fd, LOCK_EX);
  if (0 == fork ()) {
  flock (fd, LOCK_UN);
  }
  所以,有时候可以利用这些语义来将一个文件锁从父进程传输到子进程:在fork()之后,父进程关闭其文件描述符,然后锁只在子进程的控制之下了。通过fork()创建的锁在exec()中会得以保留(除非在文件描述符上设置了close-on-exec标记并且该文件描述符是后一个引用底层的打开文件描述的描述符)。
  如果程序中使用open()来获取第二个引用同一个文件的描述符,那么,flock()会将其视为不同的文件描述符。如下代码会在第二个flock()上阻塞。
  fd1 = open ("test.txt", O_RDWD);
  fd2 = open ("test.txt", O_RDWD);
  flock (fd1, LOCK_EX);
  flock (fd2, LOCK_EX);
  4. flock()的限制
  flock()放置的锁有如下限制
  只能对整个文件进行加锁。这种粗粒度的加锁会限制协作进程间的并发。假如存在多个进程,其中各个进程都想同时访问同一个文件的不同部分。
  通过flock()只能放置劝告式锁。
  很多NFS实现不识别flock()放置的锁。
  注释:在默认情况下,文件锁是劝告式的,这表示一个进程可以简单地忽略另一个进程在文件上放置的锁。要使得劝告式加锁模型能够正常工作,所有访问文件的进程都必须要配合,即在执行文件IO之前先放置一把锁。