文件的進程線程鎖

Flock 函數 互斥鎖 線程可用, 多進程可用,但fork進程不行

Fcntl 函數 多進程可用 fork進程可用 但線程不行

 

Fcntl函數的記錄鎖所用來設置對文件進行加密,所以無論是fork還是多個程序對同一個文件均可以起到加鎖的作用。但對線程則沒有作用。簡單使用可以,涉及到多進程特別是fork的話就需要注意了。因爲fork繼承此文件描述符,在fork中釋放鎖,那麼也就是主進程釋放鎖了。

 

Flock函數只能用來對整個文件加鎖,多個線程對同一個文件也可以,但是fork的進程不行。

 

所以總的來說對進程加鎖採用fcntl,需要線程安全的話就還是選擇線程鎖,比如互斥鎖,或者讀寫鎖(這個是共享互斥鎖)等。

 

下面是我的測試代碼。Wrapfcntl這兩個文件是對fcntl函數的包裝,採用<unix環境高級編程>數中的例子。這本書裏的代碼很經典的,不但瞭解函數的使用,還介紹了環境,使用注意等。比百度到的要了解的透徹多了,就像我這裏寫的,只是個筆記或者總結而已。

 

******************************** wrapfcntl.h ********************************* 

#ifndef IRIDIUMFCNTL_H

#define IRIDIUMFCNTL_H

 

#include <stdio.h>

#include <string.h>

 

#include <sys/types.h> /* about files */

#include <sys/stat.h>

#include <sys/file.h>

#include <fcntl.h>

#include <unistd.h>

#include <pthread.h>

 

/* fcntl函數的包裝,帶w表示阻塞調用*/

#define read_lock(fd, offset, whence, len) \

lock_reg((fd), F_SETLK, F_RDLCK, (offset), (whence), (len))

#define readw_lock(fd, offset, whence, len) \

lock_reg((fd), F_SETLKW, F_RDLCK, (offset), (whence), (len))

#define write_lock(fd, offset, whence, len) \

lock_reg((fd), F_SETLK, F_WRLCK, (offset), (whence), (len))

#define writew_lock(fd, offset, whence, len) \

lock_reg((fd), F_SETLKW, F_WRLCK, (offset), (whence), (len))

#define un_lock(fd, offset, whence, len) \

lock_reg((fd), F_SETLK, F_UNLCK, (offset), (whence), (len))

 

int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len);

 

#endif

 

******************************** wrapfcntl.c ********************************* 

#include "wrapfcntl.h"

 

int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)

{

struct flock lock;

 

lock.l_type = type; /* F_RDLCK, F_WRLCK, F_UNLCK */

lock.l_start = offset; /* byte offset, relative to l_whence */

lock.l_whence = whence; /* SEEK_SET, SEEK_CUR, SEEK_END */

lock.l_len = len; /* #bytes (0 means to EOF) */

 

return (fcntl(fd, cmd, &lock));

}

 

 

 

******************************** main.c ********************************* 

/*gcc main.c wrapfcntl.c  測試多進程的fcntl鎖 */

/*gcc main.c wrapfcntl.c -DTEST_FLOCK 測試多進程的flock鎖 */

 

/*gcc main.c wrapfcntl.c  -DTEST_PTHREAD -lpthread 測試多線程的fcntl鎖 */

/*gcc main.c wrapfcntl.c  -DTEST_FLOCK -lpthread 測試多線程的flock鎖 */

#include "wrapfcntl.h"

 

#define THREAD_NUM 1

void *thread_function(void *arg);  

 

const char main_process[] = "++++++++++ this is the main process \n";

const char child_process[] = "---------- this is the child process \n";

const char pthread[] = "======== this is the child thread \n";

 

//#define TEST_FLOCK

 

int fd;

const sleep_s = 10;

int main()  

{  

    int res;  

    pthread_t thread_group[THREAD_NUM];  

void *(*thread_func_group[THREAD_NUM])(void *);

 

int i;

 

char info[THREAD_NUM][20];

char temp[20];

for(i = 0; i< THREAD_NUM; i++){

sprintf(temp, "%d%d%d%d%d", i, i, i, i, i);

strcpy(info[i], temp);

}

for( i = 0; i < THREAD_NUM; i++)

thread_func_group[i] = thread_function;

    void *thread_result;  

 

int n = 0;

fd = open("/var/log/iridium/test.log", O_CREAT|O_APPEND|O_RDWR, 0744);

if(fd < 0){

printf("open error fd = %d\n", fd);

return -1;

}

#ifdef TEST_PTHREAD

printf("Testing pthread =========================\n");

#elif defined TEST_FLOCK

printf("Testing flock ==========================\n");

#else

printf("Testing multi process ==================\n");

#endif

 

#ifdef TEST_PTHREAD

   for(i = 0 ; i < THREAD_NUM; i++){

    res = pthread_create(&(thread_group[i]), NULL, thread_func_group[i], (void*)(info[i]));  

    if (res != 0)  

    {  

       perror("Thread creation failed!");  

   return -1;

    }  

   }

#else

if(fork() == 0){

while(1){

printf("child process waiting lock\n");

#ifdef TEST_FLOCK

flock(fd, LOCK_EX);

#else

writew_lock(fd, 0, SEEK_SET, 0);

#endif

n = write(fd, child_process, strlen(child_process));

if(n < 0)

printf("-----------child write error\n");

fprintf(stderr, "%s ********** after %d s unlock\n", child_process, sleep_s);

sleep(sleep_s);

#ifdef TEST_FLOCK

flock(fd, LOCK_UN);

#else

un_lock(fd, 0 ,SEEK_SET, 0);

#endif

usleep(1);

}

 

}

#endif

while(1){

printf("main\n");

#ifdef TEST_FLOCK

flock(fd, LOCK_EX);

#else

writew_lock(fd, 0, SEEK_SET, 0);

#endif

 

n = write(fd, main_process, strlen(main_process));

if(n < 0)

printf("++++++++++++++main write error\n");

fprintf(stderr, "%s ********** after %d s unlock\n",  main_process, sleep_s);

sleep(sleep_s);

#ifdef TEST_FLOCK

flock(fd, LOCK_UN);

#else

un_lock(fd, 0, SEEK_SET, 0);

usleep(1);

#endif

}

/* 忽略多個線程同時終止的問題,代碼不會執行到此,線程隨進程終止 */

  for(i = 0; i < THREAD_NUM; i++){

pthread_join(thread_group[i], NULL);

}

 

close(fd);

    return 0;

}  

  

void *thread_function(void *arg)  

{  

 

#if 1

int n = 0;

 

while(1){

#ifdef TEST_FLOCK

flock(fd, LOCK_EX);

#else

writew_lock(fd, 0, SEEK_SET, 0);

#endif

n = write(fd, pthread, strlen(pthread));

if(n < 0)

printf("=================child write error\n");

 

fprintf(stderr, "%s ********** after %d s unlock\n",  pthread, sleep_s);

sleep(sleep_s);

#ifdef TEST_FLOCK

flock(fd, LOCK_UN);

#else

un_lock(fd, 0 ,SEEK_SET, 0);

#endif

}

 

close(fd);

#endif

 

return ;

   

}  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章