El entorno Linux se convierte en sincronización de procesos [exclusión mutua / bloqueos de archivos]

El método de sincronización de subprocesos se ha introducido antes, ahora introduzcamos el método de sincronización de procesos

1. Mutex [exclusión mutua]

 Todo el mundo tiene la ilusión de que mutex solo se puede sincronizar entre subprocesos de usuario. De hecho, mutex se puede usar para la sincronización entre procesos. Antes de pthread_mutex_init, debe modificar su atributo mutex.

Las funciones de modificación del atributo mutex incluyen principalmente las siguientes

Función de aplicación principal:
pthread_mutexattr_t mattr type: se
utiliza para definir mutex, bloquear [atributo] inicializar un objeto de atributo mutex.


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

Función pthread_mutexattr_destroy :
destruir mutex, objeto de atributo (no destruir bloqueo)
int pthread_mutexattr_destroy (pthread_mutexattr_t * attr);


pthread_mutexattr_setpshared, función:
modificar atributos de 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;
}




 

2. Bloqueo de archivos

Con la ayuda de la función fcntl para realizar el mecanismo de bloqueo, cuando el proceso de operar el archivo no adquiere el bloqueo, puede abrir pero no puede realizar operaciones de lectura y escritura.

Función fcntl: obtener y establecer atributos de control de acceso a archivos.

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

Referencia 2:
F_SETLK (struct flock *) establecer bloqueo de archivo <trylock)
F_SETLKW (struct flock *) establecer bloqueo de archivo (bloquear) w -> esperarF_GETLK (struct flock *) obtener bloqueo de archivo
Referencia 3:
struct flock { short l_type; Tipo de bloqueo: F_RDLCK. F_WRLCK. F_UNLCK short l_whence; Posición de compensación: SEEK_SET, SEEK_CUR, SEEK_END off_t l_start; Compensación inicial: 1000 off_t l_len; Longitud: 0 significa que todo el archivo está bloqueado pid_t l pid; Mantiene el bloqueo ID de proceso: (solo F_GETLK) .... };








 

Demostración de bloqueo de archivo (el hilo no tiene bloqueo de archivo porque el descriptor de archivo es compartido)

#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 (exclusivo)

L_type = F_RDLCK (compartido (varios procesos pueden acceder al mismo archivo))

 

 

 

 

 

 

 

 

Supongo que te gusta

Origin blog.csdn.net/qq_44065088/article/details/109220045
Recomendado
Clasificación