linux环境变成-进程同步【互斥量/文件锁】

前面已经介绍完了线程同步的方式,现在来介绍一下进程的同步方式

一.mutex【互斥量】

 大家有一个错觉就是 以为 mutex只能用户线程间同步,其实不然mutex 其实可以用于进程间同步,在pthread_mutex_init之前,要修改他的 mutex属性就可以了

mutex属性修改的函数主要有以下几个

主要应用函数:
pthread_mutexattr_t mattr类型:
用于定义mutex,锁的【属性】初始化一个mutex.属性对象


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

pthread_mutexattr_destroy函数:
销毁mutex,属性对象(而非销毁锁)
int pthread_mutexattr_destroy(pthread_mutexattr_t*attr);


pthread_mutexattr_setpshared,函数:
修改mutex属性。
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;
}




二.文件锁

借助fcntl函数来实现锁机制,操作文件的进程没有获取锁时,可以打开但无法执行read,write操作。

fcntl函数:获取,设置文件访问控制属性。

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

参2:
F_SETLK(struct flock *)设置文件锁〈trylock)
F_SETLKW (struct flock*)设置文件锁(lock)w --> waitF_GETLK(struct flock *)获取文件锁
参3:
struct flock {

short l_type;         锁的类型:F_RDLCK . F_WRLCK . F_UNLCK
short l_whence;        偏移位置: SEEK_SET、SEEK_CUR、SEEK_END
off_t  l_start;          起始偏移:1000
off_t  l_len;          长度:0表示整个文件加锁
pid_t l pid;            持有该锁的进程ID:(F_GETLK only)
.…
};
 

文件锁Demo_(线程没有文件锁因为共享文件描述符)

#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(独享)

L_type = F_RDLCK(共享(可以多个进程访同一个文件))

猜你喜欢

转载自blog.csdn.net/qq_44065088/article/details/109220045
今日推荐