Linux文件锁的探究

参考文章:http://blog.jobbole.com/104331/

本文对flock、lockf函数的表现做验证。

这里对lockf函数在线程中的使用做了验证

void* thread( void *arg)  
{
    int fd1;
    int ret;
    fd1 = open(file,O_RDWR);
    ret = lockf(fd1,F_LOCK, 0);
    printf("child get lock, fd: %d, ret: %d\n", fd1, ret);
    return NULL;  
}  
if (strcmp(argv[1], "1")==0) {
        int fd;
        pthread_t th;  
        int ret;  
        void *thread_ret ;  
        fd = open(file,O_RDWR);
        ret = lockf(fd,F_LOCK, 0);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        ret = pthread_create( &th, NULL, thread, NULL );  
        if( ret != 0  ){  
            printf( "Create thread error!\n" );  
            return -1;  
        }  
        printf( "This is the main process.\n"  );  
        pthread_join( th, &thread_ret  );  
    }
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 1
parent get lock, fd: 3, ret: 0
This is the main process.
child get lock, fd: 4, ret: 0

上面的例子,在线程中使用了lockf函数但从结果看出,在父子线程中均可以对文件加锁,后面我们可以得出结论,文件锁在线程中是失效的,仅可以在进程中使用文件锁,线程访问同一文件可以使用互斥锁或读写锁的方式进行限制。

int ret;
int pid;
int sta;
int fd = open(file,O_RDWR);
if ((pid = fork()) == 0){
    ret = lockf(fd,F_LOCK, 0);
    printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
    printf("chile exit\n");
    exit(0);
}
ret = lockf(fd,F_LOCK, 0);
printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
printf("parent exit\n");
wait(&sta);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 2
parent get lock, fd: 3, ret: 0
parent exit

第2个例子我们可以看出打开一次文件分别在父子进程中使用lockf对文件加锁,只能有一个进程获得锁,另一个进程将处于阻塞状态。

        int ret;
        int pid;
        int sta;
        int fd = open(file,O_RDWR);
        if ((pid = fork()) == 0){
            ret = flock(fd,LOCK_EX);
            printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
            printf("chile exit\n");
            exit(0);
        }
        ret = flock(fd,LOCK_EX);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        printf("parent exit\n");
        wait(&sta);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 3
parent get lock, fd: 3, ret: 0
parent exit
chile get lock, fd: 3, ret: 0
chile exit

第3个例子我们可以看出打开一次文件分别在父子进程中使用flock对文件加锁,则父子进程均可以获得锁。

int ret;
int pid;
int sta;
int fd = open(file,O_RDWR);
if ((pid = fork()) == 0){
    int fdc = open(file, O_RDWR);
    ret = flock(fdc,LOCK_EX);
    printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
    printf("chile exit\n");
    exit(0);
}
ret = flock(fd,LOCK_EX);
printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
printf("parent exit\n");
wait(&sta);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 4
parent get lock, fd: 3, ret: 0
parent exit

第4个例子我们可以看出分别在父子进程中打开文件,使用flock对文件加锁,则只能有一个进程获得锁。

int ret;
int ret1;
int fd = open(file,O_RDWR);
ret = flock(fd, LOCK_EX);
printf("ret = %d\n", ret);
ret1 = flock(fd,LOCK_EX);
printf("ret1 = %d\n", ret1);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 5
ret = 0
ret1 = 0

第5个例子,只有一个进程,打开一次文件,重复使用flock加锁,都可以获得锁。

int ret;
int ret1;
int fd = open(file,O_RDWR);
ret = flock(fd, LOCK_EX);
printf("ret = %d\n", ret);
int fd1 = open(file,O_RDWR);
ret1 = flock(fd1,LOCK_EX);
printf("ret1 = %d\n", ret1);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 6
ret = 0

第6个例子,只有一个进程,打开两次文件,两次使用flock对不同的fd加锁,后请求加锁的将阻塞。

int ret;
int ret1;
int fd = open(file,O_RDWR);
ret = lockf(fd, F_LOCK, 0);
printf("ret = %d\n", ret);
ret1 = lockf(fd,F_LOCK, 0);
printf("ret1 = %d\n", ret1);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 7
ret = 0
ret1 = 0

第7个例子,只有一个进程,打开一次文件,重复使用lock加锁,都可以获得锁。

int ret;
int ret1;
int fd = open(file,O_RDWR);
ret = flock(fd, LOCK_EX);
printf("ret = %d\n", ret);
int fd1 = open(file, O_RDWR);
ret1 = flock(fd1,LOCK_EX);
printf("ret1 = %d\n", ret1);
zhao@bruce:~/workspace/linuxc_learn/file_learn$ ./filelock 8
ret = 0

第6个例子,只有一个进程,打开两次文件,两次使用lockf对不同的fd加锁,后请求加锁的将阻塞。

下面附上源码:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

char file[20] = "file_size";
void* thread( void *arg)  
{
    int fd1;
    int ret;
    fd1 = open(file,O_RDWR);
    ret = lockf(fd1,F_LOCK, 0);
    printf("child get lock, fd: %d, ret: %d\n", fd1, ret);
    return NULL;  
}  
int main( int argc, char *argv[]  )  
{ 
    //lockf in thread
    if (argc !=2) {
        return 0;
    }
    if (strcmp(argv[1], "1")==0) {
        int fd;
        pthread_t th;  
        int ret;  
        void *thread_ret ;  
        fd = open(file,O_RDWR);
        ret = lockf(fd,F_LOCK, 0);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        ret = pthread_create( &th, NULL, thread, NULL );  
        if( ret != 0  ){  
            printf( "Create thread error!\n" );  
            return -1;  
        }  
        printf( "This is the main process.\n"  );  
        pthread_join( th, &thread_ret  );  
    }
    //locf in fork 
    else if(strcmp(argv[1], "2")==0) {
        int ret;
        int pid;
        int sta;
        int fd = open(file,O_RDWR);
        if ((pid = fork()) == 0){
            ret = lockf(fd,F_LOCK, 0);
            printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
            printf("chile exit\n");
            exit(0);
        }
        ret = lockf(fd,F_LOCK, 0);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        printf("parent exit\n");
        wait(&sta);
    }
    //flock in fork
    else if(strcmp(argv[1],"3")==0) {
        int ret;
        int pid;
        int sta;
        int fd = open(file,O_RDWR);
        if ((pid = fork()) == 0){
            ret = flock(fd,LOCK_EX);
            printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
            printf("chile exit\n");
            exit(0);
        }
        ret = flock(fd,LOCK_EX);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        printf("parent exit\n");
        wait(&sta);
    }
    else if(strcmp(argv[1],"4")==0) {
        int ret;
        int pid;
        int sta;
        int fd = open(file,O_RDWR);
        if ((pid = fork()) == 0){
            int fdc = open(file, O_RDWR);
            ret = flock(fdc,LOCK_EX);
            printf("chile get lock, fd: %d, ret: %d\n",fd, ret);
            printf("chile exit\n");
            exit(0);
        }
        ret = flock(fd,LOCK_EX);
        printf("parent get lock, fd: %d, ret: %d\n", fd, ret);
        printf("parent exit\n");
        wait(&sta);
    }
    //dont't fork 
    else if(strcmp(argv[1],"5")==0) {
        int ret;
        int ret1;
        int fd = open(file,O_RDWR);
        ret = flock(fd, LOCK_EX);
        printf("ret = %d\n", ret);
        ret1 = flock(fd,LOCK_EX);
        printf("ret1 = %d\n", ret1);
    }
    else if(strcmp(argv[1],"6")==0) {
        int ret;
        int ret1;
        int fd = open(file,O_RDWR);
        ret = flock(fd, LOCK_EX);
        printf("ret = %d\n", ret);
        int fd1 = open(file,O_RDWR);
        ret1 = flock(fd1,LOCK_EX);
        printf("ret1 = %d\n", ret1);
    }
    else if(strcmp(argv[1],"7")==0) {
        int ret;
        int ret1;
        int fd = open(file,O_RDWR);
        ret = lockf(fd, F_LOCK, 0);
        printf("ret = %d\n", ret);
        ret1 = lockf(fd,F_LOCK, 0);
        printf("ret1 = %d\n", ret1);
    }
    else if(strcmp(argv[1],"8")==0) {
        int ret;
        int ret1;
        int fd = open(file,O_RDWR);
        ret = flock(fd, LOCK_EX);
        printf("ret = %d\n", ret);
        int fd1 = open(file, O_RDWR);
        ret1 = flock(fd1,LOCK_EX);
        printf("ret1 = %d\n", ret1);
    }

    return 0;  
}  

你可能感兴趣的:(linux,C编程)