当前位置: 首页 >> 程序设计 >> fcntl在文件记录锁的应用编程
 

fcntl在文件记录锁的应用编程

作者:piaoxiang      来源:piaoxiang.cublog.cn     发表时间:2006-11-30     浏览次数:      字号:    

中国源码网内相关主题链接
  • fcntl在文件记录锁的应用编程
  • 锁设置子函数:

    /*
     * 设置记录锁子函数lock_set.c
     *
     * 记录锁分为读取锁和写入锁,其中读取锁又称为共享锁,可以使多个
     * 进程都能够在文件的同一部分建立读取锁。而写入锁又称为互斥锁,
     * 在任何时刻只能有一个进程在文件的某个部分建立写入锁。当然,在
     * 文件的同一部分不能同时建立读取锁和写入锁。
     *
     * fcntl的lock结构如下所示:
     * struct flock {
     * short l_type;
     * off_t l_start;
     * short l_whence;
     * off_t l_len;
     * pid_t l_pid;
     * }
     *
     * 技巧:为加锁整个文件,通常的方法是将l_start说明为0,l_whence
     * 说明为SEEK_SET,l_len说明为0。
     */


    #include <stdio.h>
    #include <unistd.h>
    #include <fcntl.h>

    void print_lock(struct flock lock)
    {
            printf(" -----------------------------\n");

            if (lock.l_type == F_RDLCK) {
                    printf("\tl_type: F_RDLCK\n");
            }
            else if (lock.l_type == F_WRLCK) {
                    printf("\tl_type: F_WRLCK\n");
            }
            else if (lock.l_type == F_UNLCK) {
                    printf("\tl_type: F_UNLCK\n");
            }

            printf("\tl_start: %d\n", (int)lock.l_start);

            if (lock.l_whence == SEEK_SET) {
                    printf("\tl_whence: SEEK_SET\n");
            }
            else if (lock.l_whence == SEEK_CUR) {
                    printf("\tl_whence: SEEK_CUR\n");
            }
            else if (lock.l_whence == SEEK_END) {
                    printf("\tl_whence: SEEK_END\n");
            }

            printf("\tl_len: %d\n", (int)lock.l_len);

            printf(" -----------------------------\n");
    }

    void lock_set(int fd, int type)
    {
            struct flock lock;

            /*赋值lock结构体,加锁整个文件*/
            lock.l_whence = SEEK_SET;
            lock.l_start = 0;
            lock.l_len = 0;

            while (1) {
                    lock.l_type = type;

                    /*
                     * 根据不同的type来给文件加锁或解锁,
                     * 如果成功,则返回0,失败则返回1。
                     * 举例:如果一个文件原来已经建立了互斥锁,那么再调用fcntl
                     * 建立锁就会失败,返回-1。
                     */

                    if ((fcntl(fd, F_SETLK, &lock)) == 0) {
                            /*如果是共享锁*/
                            if (lock.l_type == F_RDLCK) {
                                    printf("read only set by %d\n", getpid());
                            }
                            /*如果是互斥锁*/
                            else if (lock.l_type == F_WRLCK) {
                                    printf("write lock set by %d\n", getpid());
                            }
                            else if (lock.l_type == F_UNLCK) {
                                    printf("release lock by %d\n", getpid());
                            }
                            print_lock(lock);
                            return;
                    }
                    else {
                            /*
                             * 获得lock的描述,也就是将文件fd的加锁信息存入到lock结构中
                             * 如果成功则返回0
                             * 如果失败则返回-1
                             */

                            if ((fcntl(fd, F_GETLK, &lock)) == 0) {
                                    if (lock.l_type != F_UNLCK) {
                                            if (lock.l_type == F_RDLCK) {
                                                    printf("read lock already set by %d\n", lock.l_pid);
                                            }
                                            else if (lock.l_type == F_WRLCK) {
                                                    printf("write lock already set by %d\n", lock.l_pid);
                                            }
                                            getchar();
                                    }
                            }
                            else {
                                    printf("cannot get the description of struck flock.\n");
                            }
                    }
            }
    }

    读取锁:

    /*
     * 测试文件读取锁
     */


    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>

    void lock_set(int, int);

    void die(char *msg)
    {
            perror(msg);
            exit(1);
    }

    int open_file(void)
    {
            int fd;

            if ((fd = open("/tmp/hello.c", O_CREAT | O_TRUNC | O_RDWR, 0666)) < 0) {
                    die("open error");
            }
            else {
                    printf("Open file: hello.c %d\n", fd);
            }

            return fd;
    }

    void close_file(int fd)
    {
            if (close(fd) < 0) {
                    die("close error");
            }
            else {
                    printf("Close file: hello.c\n");
            }
    }

    int main(void)
    {
            int fd;

            fd = open_file();

            /*给文件加写入锁*/
            lock_set(fd, F_RDLCK);
            /*等待键盘任意键触发*/
            getchar();
            /*给文件解锁*/
            lock_set(fd, F_UNLCK);
            getchar();
            close_file(fd);

            return 0;
    }

    写入锁:

    /*
     * 测试文件写入锁
     */


    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <unistd.h>

    void lock_set(int, int);

    void die(char *msg)
    {
            perror(msg);
            exit(1);
    }

    int open_file(void)
    {
            int fd;

            if ((fd = open("/tmp/hello.c", O_CREAT | O_TRUNC | O_RDWR, 0666)) < 0) {
                    die("open error");
            }
            else {
                    printf("Open file: hello.c %d\n", fd);
            }

            return fd;
    }

    void close_file(int fd)
    {
            if (close(fd) < 0) {
                    die("close error");
            }
            else {
                    printf("Close file: hello.c\n");
            }
    }

    int main(void)
    {
            int fd;

            fd = open_file();

            /*给文件加写入锁*/
            lock_set(fd, F_WRLCK);
            /*等待键盘任意键触发*/
            getchar();
            /*给文件解锁*/
            lock_set(fd, F_UNLCK);
            getchar();
            close_file(fd);

            return 0;
    }

    Makefile源文件:

    CC = gcc
    OBJS = fcntl_write fcntl_read
    CFLAGS = -Wall -g

    all: $(OBJS)

    fcntl_write: fcntl_write.c lock_set.c
            $(CC) $(CFLAGS) $^ -o $@
    fcntl_read: fcntl_read.c lock_set.c
            $(CC) $(CFLAGS) $^ -o $@

    .PHONY: clean
    clean:
            rm -rf $(OBJS)

    测试结果:

    [armlinux@lqm fcntl]$ ./fcntl_read
    Open file: hello.c 3
    read only set by 12398
       -----------------------------
            l_type: F_RDLCK
            l_start: 0
            l_whence: SEEK_SET
            l_len: 0
       -----------------------------

    release lock by 12398
       -----------------------------
            l_type: F_UNLCK
            l_start: 0
            l_whence: SEEK_SET
            l_len: 0
       -----------------------------

    Close file: hello.c
    [armlinux@lqm fcntl]$ ./fcntl_write
    Open file: hello.c 3
    write lock set by 12399
       -----------------------------
            l_type: F_WRLCK
            l_start: 0
            l_whence: SEEK_SET
            l_len: 0
       -----------------------------

    release lock by 12399
       -----------------------------
            l_type: F_UNLCK
            l_start: 0
            l_whence: SEEK_SET
            l_len: 0
       -----------------------------

    Close file: hello.c

     

    编辑 webmaster

     
     
     
    评论更多>>
     
     
    发表
     
    姓名: QQ:
    性别: MSN:
    E-mail: 主页:
    评分: 1 2 3 4 5
    评论内容:
    验证码:
      
  • 请遵守《互联网电子公告服务管理规定》及中华人民共和国其他各项有关法律法规。
  • 严禁发表危害国家安全、损害国家利益、破坏民族团结、破坏国家宗教政策、破坏社会稳定、侮辱、诽谤、教唆、淫秽等内容的评论 。
  • 用户需对自己在使用本站服务过程中的行为承担法律责任(直接或间接导致的)。
  • 本站管理员有权保留或删除评论内容。
  • 评论内容只代表网友个人观点,与本网站立场无关。
  •