Linux memoria compartida y los semáforos

Un reciente estudio de la comunicación entre el proceso de Linux. Escribí una pieza de código, para profundizar en la impresión de aprendizaje

1, la cantidad de funcionamiento de la señal de empaquetamiento

//sem_com.c
#include "sem_com.h"

//初始化信号量
int init_sem(int sem_id, int init_value)
{
	union semun sem_union;
	sem_union.val = init_value;

	if(semctl(sem_id, 0, SETVAL, sem_union) == -1)
	{
		perror("init_sem fail!");
		return -1;
	}
	return 0;
}

//删除信号量
int del_sem(int sem_id)
{
	union semun sem_union;	

	if(semctl(sem_id, 0, IPC_RMID, sem_union) == -1)
	{
		perror("del_sem fail!");
		return -1;
	}

	return 0;
}

//P操作
int sem_p(int sem_id)
{
	struct sembuf sem_b;
	
	sem_b.sem_num = 0;
	sem_b.sem_op = -1;
	sem_b.sem_flg = SEM_UNDO;

	if(semop(sem_id, &sem_b, 1) == -1)
	{
		perror("sem_p fail!");
		return -1;
	}
	
	return 1;
}

//V操作
int sem_v(int sem_id)
{
	struct sembuf sem_b;
	
	sem_b.sem_num = 0;
	sem_b.sem_op = 1;
	sem_b.sem_flg = SEM_UNDO;

	if(semop(sem_id, &sem_b, 1) == -1)
	{
		perror("sem_v fail!");
		return -1;
	}
	
	return 1;
}


//sem_com.h
#ifndef _SEM_COM_H_
#define _SEM_COM_H_
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun
{
	int val;
	struct semid_ds *buf;
	unsigned short *array;
};


//初始化信号量
int init_sem(int sem_id, int init_value);

//删除信号量
int del_sem(int sem_id);

//P操作
int sem_p(int sem_id);

//V操作
int sem_v(int sem_id);

#endif

2, el extremo de transmisión

//commun_server.c
#include "communition.h"
#include "sem_com.h"
//#include "date_type.h"

void ignor_signal(void);

int main(int argc, char *argv[])
{
	key_t key;
	int sem_id = 0;
	int shm_id = 0;
	void *shm_addr = NULL;
	SHM_DATE_TYPE shm_data = {0};
	char quit_flag[] = "quit";
	
	//  忽略一些系统信号
//	ignor_signal();

	//信号量的处理
	if((key = ftok(".", 'a')) == -1)
	{
		error_callback("ftok fail!");
	}	
	
	if((sem_id = semget(key, 1, 0666|IPC_CREAT)) == -1)
	{
		error_callback("semget fail");
	}else
	{
		printf("sem_id:%d \n", sem_id);
		init_sem(sem_id, 1);
	}

	//共享内存的处理
	if((shm_id = shmget(key, sizeof(SHM_DATE_TYPE), IPC_CREAT|0666)) == -1)
	{
		printf("11111111111111");
		del_sem(sem_id);
		error_callback("shmget fail");
	}else
	{
		shm_addr = shmat(shm_id, (void *)0, 0);
		if((void *)-1 == shm_addr)
		{
			printf("22222222222");
			del_sem(sem_id);
			error_callback("shmat fail");
		}
	}
	
	printf("shmat addr:%x\n",(int)shm_addr);	

    do
	{
		printf("\ninput some message: ");
		//抢占资源P操作
		if(sem_p(sem_id) == -1)
		{
			exit(1);
		}

		shm_data.pid = getpid();
		memset(shm_data.buffer, 0, sizeof(shm_data.buffer));
	

		if(fgets(shm_data.buffer, SHM_BUFFER_SIZE, stdin) == NULL)
		{
			del_sem(sem_id);
			error_callback("user input fail");
		}

		strncpy(shm_addr, shm_data.buffer, strlen(shm_data.buffer));
		//释放占用的资源V操作
		if(sem_v(sem_id) == -1)
		{
			exit(1);
		}
		printf("shm_data.buffer:%s\n", shm_data.buffer);

	}while((strncmp(shm_data.buffer, quit_flag, strlen(quit_flag))));

	del_sem(sem_id);

	if(shmdt(shm_addr) == -1)
	{
		error_callback("shmdt fail");
	}	

	exit(0);
	
}

void ignor_signal(void)
{
	signal(SIGSTOP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
}

3, el extremo de recepción

//commun_client.c
#include "communition.h"
#include "sem_com.h"
//#include "date_type.h"

void ignor_signal(void);

int main(int argc, char *argv[])
{
	key_t key;
	int sem_id = 0;
	int shm_id = 0;
	void *shm_addr = NULL;
	SHM_DATE_TYPE shm_data = {0};
	char quit_flag[] = "quit";
	
	//  忽略一些系统信号
//	ignor_signal();

	//信号量的处理
	if((key = ftok(".", 'a')) == -1)
	{
		error_callback("ftok fail!");
	}	
	
	if((sem_id = semget(key, 1, 0666)) == -1)
	{
		error_callback("semget fail");
	}else
	{
		printf("sem_id:%d \n", sem_id);
		//init_sem(sem_id, 1);
	}

	//共享内存的处理
	if((shm_id = shmget(key, sizeof(SHM_DATE_TYPE), IPC_CREAT|0666)) == -1)
	{
		printf("11111111111111");
		del_sem(sem_id);
		error_callback("shmget fail");
	}else
	{
		shm_addr = shmat(shm_id, (void *)0, 0);
		if((void *)-1 == shm_addr)
		{
			printf("22222222222");
			del_sem(sem_id);
			error_callback("shmat fail");
		}
	}
	
	printf("shmat addr:%x\n",(int)shm_addr);	
    
    do
	{
		if(sem_p(sem_id) == -1)
		{
			exit(1);
		}

		shm_data.pid = getpid();
		memset(shm_data.buffer, 0, sizeof(shm_data.buffer));

		strncpy(shm_data.buffer, shm_addr, strlen(shm_addr));
		printf("shm_data.buffer len:%d\n", strlen(shm_addr));
		//memcpy(shm_data, shm_addr, sizeof(SHM_BUFFER_SIZE));
		//释放占用的资源V操作
		//把内存中的数据读完之后,数据还是存在的,需要把数据在清除掉
		memset(shm_addr, 0, strlen(shm_addr));
		if(sem_v(sem_id) == -1)
		{
			del_sem(sem_id);
			shmdt(shm_id);
			exit(1);
		}
		printf("get shmbuf some::%s\n", shm_data.buffer);
	}while((strncmp(shm_data.buffer, quit_flag, strlen(quit_flag))));

	del_sem(sem_id);

	if(shmdt(shm_addr) == -1)
	{
		error_callback("shmdt fail");
	}	

	exit(0);
	
}

void ignor_signal(void)
{
	signal(SIGSTOP, SIG_IGN);
	signal(SIGINT, SIG_IGN);
	signal(SIGQUIT, SIG_IGN);
}
//communtion.h
#ifndef	 __COMMUNITION_H__ 
#define __COMMUNITION_H__
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <error.h>
#include <signal.h>
#include "date_type.h"

void error_callback(char *err_msg);

typedef struct
{
	int pid;
	char buffer[SHM_BUFFER_SIZE];
}SHM_DATE_TYPE;


#endif //__COMMUNITION_H__ 

resumen:

1, los semáforos se puede entender como una variable global, su valor es el recurso. Ocupados, liberada de recursos-1, +1, recursos.

2, cuando la operación de P, no hay recursos disponibles, que habría sido bloqueado.

3, siempre y cuando la tecla semget utiliza para crear un semáforo es lo mismo, que es para representar el mismo semáforo, esta tecla puede ser considerada la llave del semáforo?

4, la memoria compartida, la sección del mapa de memoria el espacio del núcleo en el proceso. Después de leer los datos finales de lectura, la siguiente lectura también encontró que la cola de los últimos datos restantes. Después de la finalización de cada memset lectura no reproducir este problema. Después de leer los datos y no debe ser eliminado, para ser limpiado manualmente.

 

Publicado 22 artículos originales · ganado elogios 9 · vistas 8825

Supongo que te gusta

Origin blog.csdn.net/ljm_c_bok/article/details/88777363
Recomendado
Clasificación