fopen fclose fwrite fread

 

fopen 系統會自動分配緩存,讀取文件需要的io次數會變少,速度更快

不過很不幸的是會有多進程或者多線程的錯亂問題,因此需要加鎖保證執行正確

常用鎖方式:flock,fcntl,lockf

 lock.l_type = F_WRLCK;  //F_RDLCK(讀方式加鎖) 、F_WRLCK(寫方式加鎖) 、F_UNLCK(解鎖)
 lock.l_whence = 0;    //從文件起始位置開始
 lock.l_start = 0;     //偏移值爲0
 lock.l_len = 0;       //整篇加鎖

fcntl(fd,F_SETLK,&lock),“讀共享、寫獨佔”特性,函數返回errno,

F_SETLK和F_SETLKW 用於加鎖解鎖wait阻塞,F_GETLK實際上是用於獲取文件鎖的相關信息

int flock(int fd,int operation);flock(fp->_fileno, LOCK_EX),LOCK_EX 建立互斥鎖定,LOCK_UN 解除文件鎖定

進程線程測試程序:

http://blog.chinaunix.net/uid-20682147-id-76327.html

#include<stdio.h>
#include<string>

using namespace std;
 
int main(void)
{
   FILE *fp=NULL;
   fp=fopen("hello","w+");
 
   if(NULL==fp)
   {
      return -1;
   }

	int temp=3333333;
	char s[] = "helloword";
	fprintf(fp," %s %d %f %c " ,s, temp, 22.22, 'a');

   char str[] = "This is runoob.com";
   fwrite(str, sizeof(str) , 1, fp);
	
   //fflush(fp);
   //fclose(fp);
   //fp = fopen("hello","r");

   fseek(fp, 0, SEEK_SET);

   char buffer[90] = {0};
   fread(buffer, 90, 1, fp);
   printf("fread : %s\n", buffer);

   fseek(fp, 0, SEEK_SET);

   char c;
   while(1)
   {
      c = fgetc(fp);
      if( feof(fp) )
      {
          break ;
      }
      printf("%c", c);
   }
   fclose(fp);

   //system("type hello");

   fp=NULL;
   return 0;
}
// 文件鎖flock、lockf和fcntl區別測試程序:
// 1) flock是系統調用,爲System V鎖
// 2) fcntl是系統調用,lockf是基於fcntl實現的libc庫函數,爲posix鎖
// 3) flock可以同時用於多線程和多進程互斥(x86 Linux驗證)
// 4) 而lockf和fcntl只能用於多進程
// 5) 對於NFS,只能使用fcntl,而flock只能用於本地文件系統
// 6) flock只是建議性鎖
// 7) fcntl可以實現強制性鎖
// 8) flock只能對整個文件加鎖
// 9) fcntl和lockf可以只加鎖文件的指定部分
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/wait.h>
#include <unistd.h>
// 查看鎖信息: cat /proc/locks
// 編譯方法: g++ -g -o x x.cpp -pthread -DX=3 -DZ=2
// 宏X控制是使用flock、lockf還是fcntl文件鎖,值爲1使用flock,值爲2使用lockf,值爲3使用fcntl
// 宏Z控制是多線程還是多進程,值爲1爲多線程模式,值爲2爲多進程模式

// 取當前時間,但不包括日期部分
std::string now()
{
    time_t t = time(NULL);
    struct tm tm;
    localtime_r(&t, &tm);
    char buf[sizeof("22:49:22")];
    snprintf(buf, sizeof(buf), "%02d:%02d:%02d", tm.tm_hour, tm.tm_min, tm.tm_sec);
    return buf;
}

#if X==1 // flock
int lock(const char* file)
{
    int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (-1 == fd)
    {
        printf("open error: %m\n");
        exit(1);
    }

    if (-1 == flock(fd, LOCK_EX))
    {
        printf("flock error: %m\n");
        close(fd);
        exit(1);
    }
    return fd;
}

void unlock(int fd)
{
    flock(fd, LOCK_UN);
    close(fd);
}

#elif X == 2 // lockf
int lock(const char* file)
{
    int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (-1 == fd)
    {
        printf("open error: %m\n");
        exit(1);
    }

    lseek(fd,0L,0);
    if (-1 == lockf(fd, F_LOCK, 0L))
    {
        printf("lockf error: %m\n");
        exit(1);
    }
    return fd;
}

void unlock(int fd)
{
    lseek(fd,0L,0);
    lockf(fd, F_ULOCK, 0);
    close(fd);
}

#elif X==3 // fcntl
int lock(const char* file)
{
    int fd = open(file, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
    if (-1 == fd)
    {
        printf("open error: %m\n");
        exit(1);
    }

    struct flock f;
    f.l_whence = SEEK_SET;
    f.l_start = 0;
    f.l_len = 0;
    f.l_type = F_WRLCK;
    f.l_pid = getpid();
    lseek(fd,0L,0);
    if (-1 == fcntl(fd, F_SETLKW, &f))
    {
        printf("fcntl error: %m\n");
        exit(1);
    }

    return fd;
}

void unlock(int fd)
{
    struct flock f;
    f.l_whence = SEEK_SET;
    f.l_start = 0;
    f.l_len = 0;
    f.l_type = F_UNLCK;
    f.l_pid = getpid();
    lseek(fd,0L,0);
    fcntl(fd, F_SETLKW, &f);
    close(fd);
}
#endif

void* thread1(void* param)
{
    printf("[%u][%s] to sleep 2\n", pthread_self(), now().c_str());
    sleep(2);

    printf("[%u][%s] to lock\n", pthread_self(), now().c_str());
    const char* file = (const char*)param;
    int fd = lock(file);
    printf("[%u][%s] locked\n", pthread_self(), now().c_str());

    unlock(fd);
    printf("[%u][%s] unkock and exit\n", pthread_self(), now().c_str());
    return NULL;
}

void* thread2(void* param)
{
    printf("[%u][%s] to lock\n", pthread_self(), now().c_str());
    const char* file = (const char*)param;
    int fd = lock(file);
    printf("[%u][%s] locked and sleep 6\n", pthread_self(), now().c_str());

    sleep(6);
    unlock(fd);
    printf("[%u][%s] unkock and exit\n", pthread_self(), now().c_str());
    return NULL;
}

int main(int argc, char* argv[])
{
    const char* file = "abc";
#if X==1
    printf("flock mode\n");
#elif X==2
    printf("lockf mode\n");
#elif X==3
    printf("fcntl mode\n");
#endif

#if Z==1 // 多線程模式
    printf("thread mode\n");

    pthread_t th1, th2;
    pthread_create(&th1, NULL, thread1, const_cast<char*>(file));
    pthread_create(&th2, NULL, thread2, const_cast<char*>(file));

    pthread_join(th1, NULL);
    pthread_join(th2, NULL);

#else // 多進程模式
    printf("process mode\n");

    pid_t pid1 = fork();
    if (0 == pid1)
    {
        printf("[%u][%s] to sleep 2\n", getpid(), now().c_str());
        sleep(2);

        printf("[%u][%s] to lock\n", getpid(), now().c_str());
        int fd = lock(file);
        printf("[%u][%s] locked\n", getpid(), now().c_str());
        unlock(fd);
        printf("[%u][%s] unkock and exit\n", getpid(), now().c_str());
        exit(0);
    }

    pid_t pid2 = fork();
    if (0 == pid2)
    {
        printf("[%u][%s] to lock\n", getpid(), now().c_str());
        int fd = lock(file);
        printf("[%u][%s] locked and sleep 6\n", getpid(), now().c_str());

        sleep(6);
        unlock(fd);
        printf("[%u][%s] unkock and exit\n", getpid(), now().c_str());
        exit(0);
    }

    waitpid(pid1, NULL, 0);
    waitpid(pid2, NULL, 0);
#endif

    return 0;
}

 

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