Linux System Programming 62 Advanced IO-File Lock, lockf()

File lock method:

fcntl()
lockf()
flock()


NAME
       lockf - apply, test or remove a POSIX lock on an open file

SYNOPSIS
       #include <unistd.h>

/*
fd:需要锁的目标文件
len: 要锁多长,0表示 文件有多长 锁多长,即加锁到文件末端,就算文件加长 也会随之锁上
cmd :实现的命令
F_LOCK  解锁,阻塞式加锁
F_TLOCK 尝试加锁,非阻塞式加锁
F_ULOCK 解锁
       F_TEST  测试有没有锁
*/
       int lockf(int fd, int cmd, off_t len);

Note: To
lock a file, specify fd as the parameter, and lock the file through the file descriptor. The lock is added to the file itself, that is, at the inode level, not the file attribute structure corresponding to each fd. Note: When a process opens the same file twice, the first and third used in the figure point to different file attribute structures, but they all point to the same inode file. In this case, if one adds After the lock, another close() file is executed, which will cause the locked file to be unlocked accidentally.
Insert picture description here

Experiment: Multi-process concurrency, realize that 20 processes operate the same file, and each process opens +1.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>

#define PROCNUM 20
#define FNAME "/home/mhr/Desktop/xitongbiancheng/super_io/out"
#define LINESIZE 1024


static void func_add(void)
{
	FILE *fp;
	int fd;
	char linebuf[LINESIZE];

	fp = fopen(FNAME,"r+");
	if(fp == NULL)
	{
		perror("fopen()");
		exit(1);
	}

fd = fileno(fp);//返回文件描述符
//if(fd < 0)

//上锁,加锁到文件末端
lockf(fd,F_LOCK,0);

	fgets(linebuf,LINESIZE,fp);
	fseek(fp,0,SEEK_SET);

	//sleep(1);	
	
//文件的全缓冲,而fprintf是航缓冲,所以解锁前没有close() 写操作就不能将数据写到文件中,需要ffllush()刷新流
	fprintf(fp,"%d\n",atoi(linebuf)+1);
	fflush(fp);//刷新
//解锁
lockf(fd,F_ULOCK,0);
	
//解锁后 close()  防止意外解锁
	fclose(fp);
return;

} 

int main()
{
	int i,err;
	pid_t pid;

	for(i = 0; i < PROCNUM; i++)
	{
		pid = fork();//创建20个子进程
		if(pid < 0)
		{
			perror("fork()");
			exit(1);
		}
		
		if(pid == 0)//Child 
		{
			func_add();
			exit(0);//子进程操作后就结束
		}

	}

	for(i = 0;i < PROCNUM; i++)
	{
		wait(NULL);//父进程收尸
	}

	exit(0);
	
}

Guess you like

Origin blog.csdn.net/LinuxArmbiggod/article/details/114694863