Linuxプロセス間通信の最近の研究。私は学習の印象を深めるために、コードの一部を書きました
図1に示すように、パッケージングシグナルの操作量
//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に示すように、送信端
//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に示すように、受信端
//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__
要約:
1、セマフォは、グローバル変数として理解することができる、彼の値はリソースです。占有、リソース-1、、1つのリソースを解放。
2は、ときP操作、使用可能なリソースが存在しない、それがブロックされていたであろう。
図3に示すように、限りキーsemgetからセマフォを作成するために使用されるものと同じセマフォを表すためである、同じであり、このキーはセマフォキーと見なすことができますか?
図4に示すように、共有メモリ、プロセスにおけるカーネル空間メモリマップのセクション。読み取り終了データを読んだ後、次の読み取りも、最後の残りのデータの末尾ことがわかりました。各読み取りのmemsetが完了した後、この問題を再現できません。データを読み取った後、手動でクリアするために、削除すべきではありません。