Linux shared memory and semaphores

A recent study of communication between the Linux process. I wrote a piece of code, to deepen the impression of learning

1, the amount of operation of the packaging signal

//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, the transmit end

//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, the receiving end

//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__ 

to sum up:

1, semaphores can be understood as a global variable, his value is the resource. Occupied, resource-1, released, +1 resources.

2, when the P operation, there is no available resources, it would have been blocked.

3, as long as the key semget used to create a semaphore is the same, that is to represent the same semaphore, this KEY can be considered the semaphore key?

4, shared memory, the section of the kernel space memory map in the process. After reading the read end data, the next read also found that the tail of the last remaining data. After the completion of each read memset not reproduce this problem. After reading the data and should not be removed, to be manually cleared.

 

Published 22 original articles · won praise 9 · views 8825

Guess you like

Origin blog.csdn.net/ljm_c_bok/article/details/88777363