Linux environment becomes-process synchronization [mutexes/file locks]

The thread synchronization method has been introduced before, now let’s introduce the process synchronization method

1. Mutex [mutual exclusion]

 Everyone has an illusion that mutex can only be synchronized between user threads. In fact, mutex can be used for inter-process synchronization. Before pthread_mutex_init, you need to modify its mutex attribute.

The functions of mutex attribute modification mainly include the following

Main application function:
pthread_mutexattr_t mattr type:
used to define mutex, lock [attribute] to initialize a mutex. attribute object


pthread_mutexattr_init函数:
int pthread_mutexattr_init(pthread_mutexattr_t *attr);

pthread_mutexattr_destroy function:
destroy mutex, attribute object (not destroy lock)
int pthread_mutexattr_destroy(pthread_mutexattr_t*attr);


pthread_mutexattr_setpshared, function:
modify mutex attributes.
int pthread_mutexattr. setpshared(pthread_mutexattr t *attr, int pshared);
 

#include <iostream>
#include <pthread.h>
#include <sys/mman.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

typedef int ELEMTPEY;

struct data_t
{
	ELEMTPEY elem;
	pthread_mutex_t mutex;
	pthread_mutexattr_t attr;
};


int
main(int argc, char*argv[])
{
	struct data_t *object;
	pid_t pid;
	
	// 因为是 血缘关系进程间 共享 我用的匿名映射
	object = (struct data_t*)mmap(NULL, sizeof(struct data_t), 
				PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
				
	if(object == MAP_FAILED){
		perror("mmap error");
		exit(1);
	}

	memset(object, 0, sizeof(struct data_t));
	object->elem = 0;

	pthread_mutexattr_init(&object->attr);
	pthread_mutexattr_setpshared(&object->attr, PTHREAD_PROCESS_SHARED); // 设置属性成进程间互斥量
	pthread_mutex_init(&object->mutex, &object->attr);

	srand(time(NULL));
	pid = fork();
	if(pid < 0){
		perror("fork error");
		munmap(object, sizeof(struct data_t)); // 如果创建失败 取消内存映射
		exit(1);
	}else if(pid > 0){ // son read + write
		int i=5;
		while(i--){
			pthread_mutex_lock(&object->mutex);
			printf("I am child \n");
			object->elem += 2;
			printf("the elem :%d \n", object->elem);
			pthread_mutex_unlock(&object->mutex);
			sleep(rand()%2+1);
		}
		
	}else{ // parent write
		int i=5;
		while(i--){
			pthread_mutex_lock(&object->mutex);
			printf("I am parent\n");
			object->elem++;
			printf("the elem :%d \n", object->elem);
			pthread_mutex_unlock(&object->mutex);
			sleep(rand()%2+1);
		}

		wait(NULL);
		pthread_mutexattr_destroy(&object->attr);
		pthread_mutex_destroy(&object->mutex);
		munmap(object, sizeof(struct data_t));
	}
	
	return 0;
}




 

2. File lock

With the help of the fcntl function to realize the lock mechanism, when the process of operating the file does not acquire the lock, it can open but cannot perform read and write operations.

fcntl function: get and set file access control attributes.

int fcntl(int fd, int cmd, .../* arg*/ );

Reference 2:
F_SETLK (struct flock *) set file lock <trylock)
F_SETLKW (struct flock*) set file lock (lock) w --> waitF_GETLK(struct flock *) get file lock
Reference 3:
struct flock { short l_type; Lock type: F_RDLCK. F_WRLCK. F_UNLCK short l_whence; Offset position: SEEK_SET, SEEK_CUR, SEEK_END off_t l_start; Start offset: 1000 off_t l_len; Length: 0 means that the entire file is locked pid_t l pid; Holds the lock Process ID: (F_GETLK only) .... };








 

File lock Demo_ (the thread has no file lock because the file descriptor is shared)

#include <iostream>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

using namespace std;

void
sys_err(const char* strerr)
{
	perror(strerr);
	exit(1);
}


int
main(int argc, char*argv[])
{
	int fd; 
	struct flock file_lock;

	if(argc != 2)
		sys_err("./a.out filename");
	
	if((fd = open(argv[1], O_RDWR)) < 0) 
		sys_err("open file err");

//	file_lock.l_type = F_RDLCK;
	file_lock.l_type = F_WRLCK;
	file_lock.l_whence = SEEK_SET;
	file_lock.l_start = 0;
	file_lock.l_len	= 0; 

	char buf[56];
	fcntl(fd, F_SETLKW, &file_lock);
	printf("get lock\n");
	int size = read(fd, buf, sizeof(buf));
	buf[size] = '\0';
	printf("buf:%s \n", buf);
	sleep(20);

	file_lock.l_type = F_UNLCK;
	fcntl(fd, F_SETLKW, &file_lock);
	printf("un lock\n");

	close(fd);
	return 0;
}

L_type = F_WRLCK (exclusive)

L_type = F_RDLCK (shared (multiple processes can access the same file))

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_44065088/article/details/109220045