プロセス間通信のメッセージキューと信号量
メッセージキュー
メッセージキューはIPCオブジェクトの一種であり、メッセージキューIDによって一意に識別され、メッセージキューはメッセージのリストである.ユーザは、メッセージキューにメッセージを追加したり、メッセージを読み取ることができます.
メッセージキューは、メッセージを送信/受信するためにタイプをインストールできます.メッセージ・キューの操作には、メッセージ・キューの作成またはオープン、メッセージの追加、メッセージの読み取り、メッセージの制御、メッセージの制御が含まれます.
メッセージ・キューを作成または開くには、次の手順に従います。
int msgget(key_t key,int flag); 関数パラメータ:
メッセージ関数の追加
int msgsnd(int msqid,const void * msgp,size_t size,int flag);
関数パラメータ:struct msgbuf{
long mtype; //
char mtext[N];//
};
関数の戻り値:成功0、エラー-1;
メッセージ関数の読み込み
int msgrcv(int msgid,void *msgp,size_t size,long msgtype,int flag)
関数パラメータ:-msqid:メッセージキューのID番号-msgp:メッセージを受信バッファ-size:メッセージを受信するバイト数-msgtype:1.0:受信メッセージキューの最初のメッセージ2.0より大きい、受信メッセージキューの最初のタイプがmsgtypのメッセージ3である.0より小さい場合、受信メッセージキューのタイプ値がmsgtypの絶対値より小さくなく、タイプ値が最小のメッセージ-flag:0であり、メッセージがなければ、関数はずっとブロック-IPC_NOWAIT、メッセージがなければ、プロセスはすぐにENOMSGに戻る
関数の戻り値:正常に受信されたメッセージの長さ.失敗は-1を返します.
制御メッセージ使用関数:
int msgctl(int msgqid,int cmd,struct msqid_ds*buf)関数パラメータ:-msgqidメッセージキューID-cmd:1.IPC_STATは、メッセージキューの属性を読み出す、bufが実行するバッファに格納する.IPC_SETは、bufパラメータ3から取得するメッセージキューの属性を設定する.IPC_RMIDシステムからメッセージキュー-bufを削除する:メッセージキューバッファ
関数の戻り値:成功0、失敗-1;
#include
#include
#include
#include
#include
#include
#define BFUSZ 512
#define TYPE 100
struct msgbuf{
long mtype;
char mtext[BFUSZ];
};
int main()
{
int qid,len;
key_t key;
struct msgbuf msg;
if( (key = ftok(".",'a'))== -1)
{
perror("ftok");
exit(-1);
}
if( (qid = msgget(key,IPC_CREAT|0666)) == -1)
{
perror("msgget");
exit(-1);
}
printf("opened queue%d
",qid);
if( (fgets((&msg)->mtext,BFUSZ,stdin))==NULL)
{
puts("no message");
exit(-1);
}
msg.mtype = TYPE;
len = strlen(msg.mtext)+1;
if( msgsnd(qid,&msg,len,0)<0)
{
perror("msgsnd");
exit(-1);
}
if( msgrcv(qid,&msg,BFUSZ,0,0)<0)
{
perror("msgrcv");
exit(-1);
}
printf("message is: %s
",(&msg)->mtext);
if(msgctl(qid,IPC_RMID,NULL)<0)
{
perror("msgctl");
exit(1);
}
return 0;
}
しんごうりょう
信号灯(semaphore)は信号量とも呼ばれます.これは、異なるプロセス間または同じプロセス内の異なるスレッド間で同期するメカニズムです.
信号灯種類:-posix有名信号灯-posixメモリベース信号灯(無名信号灯)-System V信号灯(IPC対象)
System V信号灯は、1つまたは複数の信号灯の集合である.いずれも遅延カウント信号ランプです.Posix信号は単一の信号です
System V信号はカーネルによって維持されます.主要関数semget,semop,semctl
int semget(key_t key , int nsems,int semflg);
関数パラメータ:-key:信号セットに関連付けられたkey値-nsems:信号セットに含まれる信号セットの数-semflg信号セットへのアクセス権は、通常IPC_CREAT|0666
関数戻り値:成功信号セットID失敗-1;
int semop(int semid ,struct sembuf * opsptr,size_t nops);
関数パラメータ:-semid:信号セットID
struct sembuf{
short sem_num; //
short sem_op; //0: , 0
//1: ,V
//-1: ,P
short sem_flg; //0,IPC_NOWAIT,SEM_UNDO
};
/*********************** read ************************************/
#include
#include
#include
#include
#include
#include
#include
#include
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#define N 64
#define READ 0
#define WRITE 1
void sem_init(int semid, int array[], int n)
{
union semun myun;
int i;
for (i=0; iarray[i];
semctl(semid, i, SETVAL, myun);
}
return;
}
void pv(int semid, int num, int op)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
if (semop(semid, &buf, 1) < 0)
{
exit(0);
}
return;
}
int main()
{
key_t key;
int shmid, semid;
char *shmaddr;
int array[] = {0, 1};
if ((key = ftok(".", 's')) < 0)
{
perror("fail to ftok");
exit(-1);
}
if ((semid = semget(key, 2, 0666|IPC_CREAT|IPC_EXCL)) < 0)
{
if (EEXIST == errno)
{
semid = semget(key, 2, 0666);
}
else
{
perror("fail to semget");
exit(-1);
}
}
else
{
sem_init(semid, array, 2);
}
if ((shmid = shmget(key, N, 0666|IPC_CREAT)) < 0)
{
perror("fail to shmget");
exit(-1);
}
shmaddr = (char *)shmat(shmid, NULL, 0);
while ( 1 )
{
pv(semid, READ, -1);
printf("read from shm : %s", shmaddr);
pv(semid, WRITE, 1);
}
return 0;
}
/********************************** write ********************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
union semun {
int val; /* Value for SETVAL */
struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
unsigned short *array; /* Array for GETALL, SETALL */
struct seminfo *__buf; /* Buffer for IPC_INFO
(Linux-specific) */
};
#define N 64
#define READ 0
#define WRITE 1
void sem_init(int semid, int array[], int n)
{
union semun myun;
int i;
for (i=0; iarray[i];
semctl(semid, i, SETVAL, myun);
}
return;
}
void pv(int semid, int num, int op)
{
struct sembuf buf;
buf.sem_num = num;
buf.sem_op = op;
buf.sem_flg = 0;
semop(semid, &buf, 1);
return;
}
int main()
{
key_t key;
int shmid, semid;
char *shmaddr;
int array[] = {0, 1};
if ((key = ftok(".", 's')) < 0)
{
perror("fail to ftok");
exit(-1);
}
if ((semid = semget(key, 2, 0666|IPC_CREAT|IPC_EXCL)) < 0)
{
if (EEXIST == errno)
{
semid = semget(key, 2, 0666);
}
else
{
perror("fail to semget");
exit(-1);
}
}
else
{
sem_init(semid, array, 2);
}
if ((shmid = shmget(key, N, 0666|IPC_CREAT)) < 0)
{
perror("fail to shmget");
exit(-1);
}
shmaddr = (char *)shmat(shmid, NULL, 0);
while ( 1 )
{
pv(semid, WRITE, -1);
printf("write to shm : ");
fgets(shmaddr, N, stdin);
if (strncmp(shmaddr, "quit
", 5) == 0) break;
pv(semid, READ, 1);
}
shmdt(shmaddr);
shmctl(shmid, IPC_RMID, NULL);
semctl(semid, 0, IPC_RMID);
return 0;
}