Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31079
  • 博文数量: 11
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 131
  • 用 户 组: 普通用户
  • 注册时间: 2015-04-14 19:23
个人简介

a person

文章分类

全部博文(11)

文章存档

2015年(11)

我的朋友

分类: C/C++

2015-04-26 02:40:51


  1. #include <unistd.h>
  2.        #include <fcntl.h>

  3.        int fcntl(int fd, int cmd, ... /* arg */ );
fcntl主要对打开的文件描述符执行本文以下描述的几类操作;根据cmd参数执行相应操作,cmd在下面描述中列出;
1. 复制文件描述符
    F_DUPFD  找出最小的可用的文件描述符或者大于等于arg的文件描述符作为fd的拷贝;
    如 fcntl(fd,F_DUPFD,0)等价于 dup(fd);

点击(此处)折叠或打开

  1. int main(void){
  2.     int fd=fcntl(STDOUT_FILENO,F_DUPFD,0);
  3.     if(fd<0){
  4.         fprintf(stderr,"fcntl dupfd error %d\n",fd);
  5.         exit(1);
  6.     }
  7.     printf("duplicate fd %d\n",fd);

  8.     exit(0);
  9. }
2.文件描述符标记位的读取和设置
F_GETFD 读取文件描述符标记,此时arg参数忽略
F_SETFD 设置文件描述符标记,文件描述标记设置位arg;当前只有一个FD_CLOEXEC

3.文件状态标记的读取和设置
F_GETFL 获取文件的访问模式和文件的状态标记,此时arg参数忽略
F_SETFL 将arg设置为文件的访问模式(O_RDONLY, O_WRONLY,O_RDWR)和创建标记(O_CREAT, O_EXCL, O_TRUNC...)

4.咨询锁(Advisory Locking)
F_GETLK F_SETLK F_SETLKW用来获取、释放、测试存在的记录锁(也称为文件片段或文件区域锁),第三个参数lock是一个指针;
        F_GETLK  如果试图锁定一个已经被锁定的文件,将会返回-1,并且errno设置为EACESS或者EAGAIN;
        F_SETLKW   如果试图锁定一个已经被锁定的文件,调用进程将会阻塞等待,直到锁释放或者被信号中断;
当放置一个“读”锁时,确保文件描述符时打开的;当放置一个“写”锁,确保文件描述符可读可写;

点击(此处)折叠或打开

  1. struct flock {
  2.                ...
  3.                short l_type; /* Type of lock: F_RDLCK,
  4.                                    F_WRLCK, F_UNLCK */
  5.                short l_whence; /* How to interpret l_start:
  6.                                    SEEK_SET, SEEK_CUR, SEEK_END */
  7.                off_t l_start; /* Starting offset for lock */
  8.                off_t l_len; /* Number of bytes to lock */
  9.                pid_t l_pid; /* PID of process blocking our lock
  10.                                    (F_GETLK only) */
  11.                ...
  12.            };
l_type指定了锁的类型 F_RDLCK , F_WRLCK, F_UNLCK;多个进程能够共享“读”锁(共享锁),但是一次只能由一个进程享有“写”锁(互斥锁);
  
l_whence 指定了锁定的开始位置  
    SEEK_SET文件的开头;
    SEEK_CUR文件中指针的当前位置;
    SEEK_END文件的末尾;
l_start 指定了相对开始位置的偏移位置;
l_len    指定了锁定文件的字节数
l_pid    指定了阻塞当前锁的进程PID;

在设定读写锁时,由于标准库中的读写操作具有缓存,应该直接使用read,write 系统函数;

通常在linux系统中会看到很多以.pid结尾的文件,比如mongodb里面就有一个lock.pid,这个文件就是一个使用以上的锁机制创建的锁文件,主要目的是为了保证daemon程序的单例,即同一个daemon程序一次只能运行一个;当一个daemon开始运行,就会创建一个文件,并锁定,通常该文件的内容时该进程的pid,当在运行该进程时,就会发生错误;因为文件锁机制保证了该daemon的单例性;
下面就通过一个程序来演示fcntl的文件锁机制。
头文件"myfcntl.h"

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <errno.h>
  6. #include <sys/types.h>

  7. #define error_handle(en,msg) \
  8.     do{errno=en;perror(msg);exit(EXIT_FAILURE);}while(0)

  9. int lockfile(int fd){
  10.     struct flock fl;

  11.     fl.l_type=F_WRLCK;
  12.     fl.l_start=0;
  13.     fl.l_whence=SEEK_SET;
  14.     fl.l_len=0;
  15.     return(fcntl(fd,F_SETLK,&fl));
  16. }
  17. ~
singlerun.c

点击(此处)折叠或打开

  1. #include <unistd.h>
  2. #include <fcntl.h>
  3. #include <stdlib.h>
  4. #include <stdio.h>
  5. #include <syslog.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include <sys/stat.h>

  9. #define LOCKFILE "/home/yamorn/daemon.pid"
  10. #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)

  11. extern int lockfile(int);

  12. int already_running(void){
  13.     int fd;
  14.     char buf[16];

  15.     fd=open(LOCKFILE,O_RDWR|O_CREAT,LOCKMODE);
  16.     if(fd<0){
  17.         syslog(LOG_ERR,"can't open %s: %s",LOCKFILE,strerror(errno));
  18.         exit(1);
  19.     }
  20.     if(lockfile(fd)<0){
  21.         if(errno==EACCES||errno==EAGAIN){
  22.             close(fd);
  23.             return(1);
  24.         }
  25.         syslog(LOG_ERR,"can't lock %s: %s",LOCKFILE,strerror(errno));
  26.         exit(1);
  27.     }
  28.     ftruncate(fd,0);
  29.     sprintf(buf,"%ld",(long)getpid());
  30.     write(fd,buf,strlen(buf)+1);
  31.     return(0);
  32. }






阅读(798) | 评论(0) | 转发(0) |
0

上一篇:umask

下一篇:创建Daemon进程

给主人留下些什么吧!~~