linux 文件锁、系统调用和库函数之间的关系

来源:互联网 发布:怎么把淘宝店做好 编辑:程序博客网 时间:2024/05/21 22:45

下面介绍文件锁以及系统调用和库函数之间的关系。

文件锁:

什么是文件锁?

文件锁就是给文件上了一把锁,在进程使用文件的时候加锁,在进程结束的时候解开。

为什么加文件锁?

多个进程在同时访问一个文件的时候,避免文件的错误。

文件锁分为:读锁(建议锁)    写锁(互斥锁)

锁的实现分为:建议锁  强制锁

下面介绍建议锁:

函数fcntl(2) 

 #include <unistd.h>
 #include <fcntl.h>
 int fcntl(int fd, int cmd, ... /* arg */ );

功能:操控文件描述符

参数:fd-文件描述符

         cmd:

              F_GETLK :测试是否可以加锁,如果可以加锁返回的lock的l_type字段设置为F_UNLCK。如果不能加锁,将hold这锁的进程                              的pid 设置在lock的l_pid成员中
              F_SETLK :给文件加锁的区域,添加或释放一把锁。如果在文件加锁的区域已经有程hold着一把互斥锁,里就返回-1.errno                             被设置为EACCES 和  EAGAIN互斥锁
              F_SETLKW:和F_SETLK一样,但是在另外进程hold着资源的时候,阻塞等待另外进程释放文件锁。

           struct flock {               ...               short l_type;    /* Type of lock: F_RDLCK,                                   F_WRLCK, F_UNLCK */               short l_whence;  /* How to interpret l_start:                                   SEEK_SET, SEEK_CUR, SEEK_END */               off_t l_start;   /* Starting offset for lock */               off_t l_len;     /* Number of bytes to lock */               pid_t l_pid;     /* PID of process blocking our lock                                   (F_GETLK only) */               ...           };                                             手册里有  man 2 fcntl
返回值:成功返回0  失败返回-1

演示代码如下(两个文件):

locka.c:

  2 #include <unistd.h>  3 #include <fcntl.h>  4 int main(int argc,char *argv[]){  5     int fd=open(argv[1],O_RDONLY);  6     if(fd==-1){  7         perror("open");  8         return -1;  9     } 10     struct flock lock; 11     lock.l_type=F_RDLCK; 12     lock.l_whence=SEEK_SET; 13     lock.l_start=0; 14     lock.l_len=10; 15     fcntl(fd,F_SETLK,&lock); 16     getchar(); 17     close(fd); 18 }
lockb.c

  1 #include<stdio.h>  2 #include <unistd.h>  3 #include <fcntl.h>  4 int main(int argc,char *argv[]){  5     int fd=open(argv[1],O_WRONLY);  6     if(fd==-1){  7         perror("open");  8         return -1;  9     } 10     struct flock lock; 11     lock.l_type=F_WRLCK; 12     lock.l_whence=SEEK_SET; 13     lock.l_start=0; 14     lock.l_len=10; 15     fcntl(fd,F_SETLKW,&lock); 16     printf("lock success...\n"); 17     close(fd); 18 }
先执行文件locka,运行之后因为getchar()原因会在当前等待下一步操作,这时候我们执行文件lockb.c(一个新窗口或者把locka.c 用Ctrl+z 进入后台),可以看到结果也会一直等待,他在等待我们文件locka.c运行完毕(F_SETLKW),当我们给locka.c运行结果一个任意操作,让他的结束。就会看到lockb.c输出printf("lock success...\n")。


下面介绍系统调用和库函数之间的关系:

 库函数,fopen(3)   fclose(3)    fputc(3)      fgetc(3)
 系统调用  open(2)    close(2)   read(2)   write(2)

首先使用fopen的时候会定义一个FILE

typedef struct _IO_FILE FILE;
查看预编译文件可以看出实际上FILE是一个结构体(他的一部分成员如下截图)的变量的别名。 FILE *new 定义了一个结构体指针指向该结构体!

结构体会占用空间系统会分配空间给该结构体  FILE * new=malloc(sizeof(FILE))

缓存的读写区域的地址与结构体相应的成员一一对应。

 结构体里的一个参数 new->文件描述符(fileno)=open()   在通过系统调用去打开一个文件

当我们要从文件得到数据的时候,这时候如果数据的缓存区域有数据,就会直接将数据返回。如果没有数据就会调用read()函数从文件中读取数据到缓存,然后在返回。   read(fd->fileno,buf(缓存),1024);

当我们要向文件中写入数据的时候,也会判断缓存区满了没,满了就调用write()函数将数据写入文件,这时候没满也会用fflush()将缓存区的内容刷新,强制调用write()函数,将内容写进文件。

我们要关闭文件的时候会先清理缓存,然后释放缓存,然后调用close()关闭文件,最后释放FILE对象所占的空间。


大笑