C語(yǔ)言中進(jìn)程間通訊的方式詳解
一.無(wú)名管道
1.1無(wú)名管道的原理
無(wú)名管道只能用于親緣間進(jìn)程的通信,無(wú)名管道的大小是64K。無(wú)名管道是內(nèi)核空間實(shí)現(xiàn)的機(jī)制。
1.2功能
1) Pipe()創(chuàng)建一個(gè)管道,這是一個(gè)單向的數(shù)據(jù)通道,可用于進(jìn)程間通信。
2)數(shù)組pipefd用于返回兩個(gè)指向管道末端的文件描述符。
3)Pipefd[0]指的是管道的讀端。Pipefd[1]指的是管道的寫(xiě)入端,寫(xiě)入管道的寫(xiě)入端數(shù)據(jù)由內(nèi)核進(jìn)行緩沖(64k),直到從管道的讀取端讀取為止。
1.3無(wú)名管道通信特點(diǎn)
1.只能用于親緣間進(jìn)程的通信
2.無(wú)名管道數(shù)據(jù)半雙工的通信的方式
單工 : A -------------->B
半雙工 : 同一時(shí)刻 A----->B B------>A
全雙工 : 同一時(shí)刻 A<---->B
3.無(wú)名管道的大小是64K
4.無(wú)名管道不能夠使用lseek函數(shù)
5.讀寫(xiě)的特點(diǎn)
如果讀端存在寫(xiě)管道:有多少寫(xiě)多少,直到寫(xiě)滿(mǎn)為止(64k)寫(xiě)阻塞
如果讀端不存寫(xiě)管道,管道破裂(SIGPIPE) (可以通過(guò)gdb調(diào)試看現(xiàn)象)
如果寫(xiě)端存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候阻塞等待
如果寫(xiě)端不存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候立即返回
1.4無(wú)名管道的實(shí)例
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <string.h> #include <sys/wait.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { pid_t pid; int num[2]; char buff[128] = {0}; if (pipe(num)){ ERROR("pipe error"); } if ((pid = fork()) == -1){ ERROR("fork error"); }else if(pid == 0){ close(num[0]); while (1){ memset(buff, 0, sizeof(buff)); printf("請(qǐng)輸入您要輸入的數(shù)值>>"); fgets(buff, sizeof(buff), stdin); buff[strlen(buff) -1] = '\0'; write(num[1], buff, strlen(buff)); if (!strncmp(buff, "quit", 4)){ break; } } close(num[1]); exit(EXIT_SUCCESS); }else{ close(num[1]); while (1){ memset(buff, 0, sizeof(buff)); read(num[0], buff, sizeof(buff)); if (!strncmp(buff, "quit", 4)){ break; } printf("%s\n",buff); } close(num[0]); wait(NULL); } return 0; }
二.有名管道
2.1有名管道的原理
1)可以用于親緣間進(jìn)程的通信,也可以用于非親緣間的進(jìn)程的通信。
2)有名管道會(huì)創(chuàng)建一個(gè)文件,需要通信的進(jìn)程打開(kāi)這個(gè)文件,產(chǎn)生文件描述符后就可以通信了,有名管道的文件存在內(nèi)存上。
3)有名管道的大小也是64K,也不能使用lseek函數(shù)
2.2有名管道的特點(diǎn)
1.可以用于任意進(jìn)程間的通信
2.有名管道數(shù)據(jù)半雙工的通信的方式
3.有名管道的大小是64K
4.有名管道不能夠使用lseek函數(shù)
5.讀寫(xiě)的特點(diǎn)
如果讀端存在寫(xiě)管道:有多少寫(xiě)多少,直到寫(xiě)滿(mǎn)為止(64k)寫(xiě)阻塞
如果讀端不存寫(xiě)管道
1.讀權(quán)限沒(méi)有打開(kāi),寫(xiě)端在open的位置阻塞
2.讀端打開(kāi)后關(guān)閉,管道破裂(SIGPIPE) (可以通過(guò)gdb調(diào)試看現(xiàn)象)
如果寫(xiě)端存在讀管道:有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候阻塞等待
如果寫(xiě)端不存在讀管道
1.寫(xiě)權(quán)限沒(méi)有打開(kāi),讀端在open的位置阻塞
2.寫(xiě)端打開(kāi)后關(guān)閉,有多少讀多少,沒(méi)有數(shù)據(jù)的時(shí)候立即返回
2.3有名管道實(shí)例
mkfifo文件:
#include <stdio.h> #include <stdlib.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { if (mkfifo("./fifo",0666)){ ERROR("mkfifo error"); } //有名管道沒(méi)有阻塞,手動(dòng)加一個(gè)阻塞 getchar(); system("rm ./fifo -rf"); return 0; }
write文件:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { int fd; char buff[128] = {0}; if ((fd = open("./fifo",O_WRONLY)) == -1){ ERROR("open fifo error\n"); } while(1){ printf("input >"); fgets(buff, sizeof(buff), stdin); buff[strlen(buff) - 1] = '\0'; write(fd, buff, strlen(buff)); if(!strncmp("quit",buff,4))break; } close(fd); return 0; }
read文件:
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #define ERROR(msg) \ do \ { \ printf("%s %s %d\n", __FILE__, __func__, __LINE__); \ printf(msg); \ exit(-1); \ } while (0) int main(int argc, char const *argv[]) { int fd; char buff[128] = {0}; if ((fd = open("./fifo", O_RDONLY)) == -1) { ERROR("open error"); } while (1){ memset(buff, 0, sizeof(buff)); read(fd, buff, sizeof(buff)); if (!strncmp("quit",buff,4)){ break; } printf("%s\n",buff); } close(fd); return 0; }
三.信號(hào)
3.1信號(hào)的概念
信號(hào)是中斷的一種軟件模擬,中斷是基于硬件實(shí)現(xiàn)的,信號(hào)是基于linux內(nèi)核實(shí)現(xiàn)的。
用戶(hù)可以給進(jìn)程發(fā)信號(hào),進(jìn)程可以給進(jìn)程發(fā)信號(hào),內(nèi)核也可以給進(jìn)程發(fā)信號(hào)。進(jìn)程對(duì)
信號(hào)的處理方式有三種:捕捉,忽略,默認(rèn)
3.2發(fā)送信號(hào)的函數(shù)
int raise(int sig);
功能:給自己(進(jìn)程或者線程)發(fā)信號(hào)
參數(shù):
@sig:信號(hào)號(hào)
返回值:成功返回0,失敗返回非0
int kill(pid_t pid, int sig);
功能:給進(jìn)程發(fā)信號(hào)
參數(shù):
@pid:進(jìn)程號(hào)
- pid > 0 :給pid對(duì)應(yīng)的進(jìn)程發(fā)信號(hào)
- pid = 0 :給同組的進(jìn)程發(fā)信號(hào)
- pid = -1:給所有的有權(quán)限操作的進(jìn)程發(fā)送信號(hào),init進(jìn)程除外
- pid < -1:給-pid對(duì)應(yīng)的同組的進(jìn)程發(fā)信號(hào)
@sig:信號(hào)號(hào)
返回值:成功返回0,失敗返回-1置位錯(cuò)誤碼
3.3常用的信號(hào)
1.在上述的信號(hào)中只有SIGKILL和SIGSTOP兩個(gè)信號(hào)不能被捕捉也不能被忽略
2.SIGCHLD,當(dāng)子進(jìn)程結(jié)束的時(shí)候,父進(jìn)程收到這個(gè)SIGCHLD的信號(hào)
3.4實(shí)例
捕捉ctrl+c
#include <stdio.h> #include <signal.h> #include <stdlib.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) void handle(int num) { if (num == SIGINT){ printf("我收到一個(gè)ctrl+c的信號(hào)\n"); } } int main(int argc, char const *argv[]) { //捕捉 if (signal(SIGINT, handle) == SIG_ERR){ ERROR("register signal error"); } //忽略 if (signal(SIGINT,SIG_IGN) == SIG_ERR){ ERROR("register signal error"); } //默認(rèn) if (signal(SIGINT,SIG_DFL) == SIG_ERR){ ERROR("register signale"); } while(1); return 0; }
捕捉管道破裂的消息
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) void handle(int num) { if (num == SIGPIPE){ printf("捕捉到一條管道破裂的消息\n"); } } int main(int argc, char const *argv[]) { int num[2]; char buff[32] = "123"; if(pipe(num)){ ERROR("pipe error"); } if (signal(SIGPIPE,handle) == SIG_ERR){ ERROR("signal error"); } close(num[0]); write(num[1],buff,strlen(buff)); return 0; }
阻塞等待為子進(jìn)程回收資源
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #include <string.h> void signal_handle(int signo) { printf("我是父進(jìn)程,收到了子進(jìn)程退出的信號(hào),為它回收資源\n"); waitpid(-1,NULL,WNOHANG); //非阻塞方式回收資源 printf("為子進(jìn)程回收資源成功\n"); raise(SIGKILL); //給父進(jìn)程發(fā)送信號(hào),結(jié)束父進(jìn)程 } int main(int argc,const char * argv[]) { pid_t pid; pid = fork(); if(pid == -1){ ERROR("fork error"); }else if(pid == 0){ sleep(5); printf("子進(jìn)程執(zhí)行結(jié)束了\n"); exit(EXIT_SUCCESS); }else{ if(signal(SIGCHLD,signal_handle)==SIG_ERR) ERROR("signal error"); while(1); } return 0; }
用arlarm實(shí)現(xiàn)一個(gè)斗地主機(jī)制
#include <stdio.h> #include <signal.h> #include <stdlib.h> #include <unistd.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) void handle(int num) { if (num == SIGALRM){ printf("自動(dòng)出牌\n"); } alarm(3); } int main(int argc, char const *argv[]) { char ch; if (signal(SIGALRM,handle) == SIG_ERR){ ERROR("signale error"); } alarm(3); while (1){ printf("請(qǐng)輸入您要出的牌>>"); ch = getchar(); getchar(); printf("%c\n",ch); alarm(3); } return 0; }
四.IPC進(jìn)程間通信
4.1IPC進(jìn)程間通信的種類(lèi)
(1)消息隊(duì)列
(2)共享內(nèi)存
(3)信號(hào)燈集
4.2查看IPC進(jìn)程間通信的命令
4.2.1查看
ipcs -q //查看消息隊(duì)列的命令
ipcs -m //查看共享內(nèi)存的命令
ipcs -s //查看信號(hào)燈集的命令
4.2.2刪除ipc的命令
ipcrm -q msqid //刪除消息隊(duì)列命令
ipcrm -m shmid //刪除共享內(nèi)存命令
ipcrm -s semid //刪除信號(hào)燈集的命令
4.3消息隊(duì)列
4.3.1消息隊(duì)列的原理
消息隊(duì)列也是借助內(nèi)核實(shí)現(xiàn)的,A進(jìn)程將消息放到消息隊(duì)列中,隊(duì)列中的消息
有消息的類(lèi)型和消息的正文。B進(jìn)程可以根據(jù)想取的消息的類(lèi)型從消息隊(duì)列中
將消息讀走。消息隊(duì)列默認(rèn)的大小是16384個(gè)字節(jié)。如果消息隊(duì)列中的消息滿(mǎn)了,
A進(jìn)程還想往隊(duì)列中發(fā)消息,此時(shí)A進(jìn)程阻塞。
4.3.2IPC進(jìn)程間通信鍵值的獲取
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #define ERROR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { key_t key; struct stat st; if ((key = ftok("/home/linux",'w')) == -1){ ERROR("ftok error"); } printf("key=%#x\n",key); if (stat("/home/linux",&st)){ ERROR("stat error"); } printf("pro_id=%#x,devno=%#lx,ino=#=%#lx\n",'w',st.st_dev,st.st_ino); return 0; }
結(jié)果圖:
4.3.3消息隊(duì)列的實(shí)例:(不關(guān)注類(lèi)型的)
頭文件:
#ifndef __MYHEAD_H__ #define __MYHEAD_H__ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <sys/msg.h> #include <string.h> #define PRINT_ERR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) #define MSGSIZE (sizeof(msg_t)-sizeof(long)) typedef struct mubuf{ long mtype; char text[512]; }msg_t; #endif
發(fā)送方:
#include "myhead.h" int main(int argc, char const *argv[]) { key_t key; int msqid; msg_t msg ={ .mtype = 100, }; if((key = ftok("/home/linux/",'r'))==-1) PRINT_ERR("ftok get key error"); if((msqid = msgget(key,IPC_CREAT|0666))==-1) PRINT_ERR("create msg queue error"); while (1){ memset(msg.text,0,sizeof(msg.text)); fgets(msg.text,MSGSIZE,stdin); msg.text[strlen(msg.text) - 1] = '\0'; msgsnd(msqid, &msg, MSGSIZE, 0); if (!strncmp(msg.text,"quit",4)){ break; } } msgctl(msqid, IPC_RMID, NULL); return 0; }
接受方:
#include "myhead.h" int main(int argc, char const *argv[]) { key_t key; int msgqid; msg_t msg; if ((key = ftok("/home/linux",'r')) == -1){ PRINT_ERR("ftok error"); } if ((msgqid = msgget(key, IPC_CREAT|0666)) == -1){ PRINT_ERR("msgget error"); } while (1){ memset(msg.text, 0, sizeof(msg.text)); msgrcv(msgqid, &msg, MSGSIZE,0,0); if (!strncmp("quit",msg.text,4)){ break; } printf("%s\n",msg.text); } msgctl(msgqid,IPC_RMID,NULL); return 0; }
4.3.4消息隊(duì)列的實(shí)例:(關(guān)注類(lèi)型的)
頭文件:
#ifndef __MSGQUE_H__ #define __MSGQUE_H__ #include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/stat.h> #include <unistd.h> #include <stdlib.h> #include <sys/msg.h> #include <string.h> typedef struct msgbuf { long id; char name[30]; char sex; int age; }msg_t; #define MSGSIZE (sizeof(msg_t)-sizeof(long)) #endif
發(fā)送方:
#include "msgqueue.h" #include <head.h> int main(int argc, const char* argv[]) { key_t key; int msqid; if ((key = ftok("/home/linux/", 'r')) == -1) PRINT_ERR("ftok get key error"); if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1) PRINT_ERR("create msg queue error"); msg_t m1 = { .id = 1, .name = "zhangsan", .sex = 'm', .age = 30, }; msgsnd(msqid, &m1, MSGSIZE, 0); msg_t m2 = { .id = 2, .name = "lisi", .sex = 'w', .age = 18, }; msgsnd(msqid, &m2, MSGSIZE, 0); msg_t m3 = { .id = 3, .name = "wangwu", .sex = 'm', .age = 22, }; msgsnd(msqid, &m3, MSGSIZE, 0); // msgctl(msqid, IPC_RMID, NULL); return 0; }
接受方:
#include "msgqueue.h" int main(int argc, const char* argv[]) { key_t key; int msqid; msg_t msg; if ((key = ftok("/home/linux/", 'r')) == -1) PRINT_ERR("ftok get key error"); if ((msqid = msgget(key, IPC_CREAT | 0666)) == -1) PRINT_ERR("create msg queue error"); memset(&msg, 0, sizeof msg); msgrcv(msqid, &msg, MSGSIZE, atoi(argv[1]), 0); printf("id=%ld,name=%s,sec=%c,age=%d\n",msg.id,msg.name,msg.sex,msg.age); // msgctl(msqid, IPC_RMID, NULL); return 0; }
結(jié)果圖:
4.4共享內(nèi)存
4.4.1原理:
共享內(nèi)存:在內(nèi)核空間創(chuàng)建共享內(nèi)存,讓用戶(hù)的A和B進(jìn)程都能夠訪問(wèn)到。通過(guò)這塊內(nèi)存
進(jìn)行數(shù)據(jù)的傳遞。共享內(nèi)存所有的進(jìn)程間通信中效率最高的方式(不需要來(lái)回拷貝數(shù)據(jù)),共享內(nèi)存的大小為 4k整數(shù)倍。
4.4.2實(shí)例
接受方:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <stdlib.h> #define PRINT_ERR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { key_t key; int shmid; char* over; if ((key = ftok("/home/linux", 'r')) == -1){ PRINT_ERR("ftok error"); } if ((shmid = shmget(key, 4096, IPC_CREAT|0666)) == -1){ PRINT_ERR("shemget error"); } if ((over = shmat(shmid, NULL, 0)) == (void*)-1){ PRINT_ERR("shmat error"); } while (1){ if (!strncmp("quit", over, 4))break; getchar(); printf("%s\n",over); } if (shmdt(over)){ PRINT_ERR("shmdt error"); } shmctl(shmid,IPC_RMID,NULL); return 0; }
發(fā)送方:
#include <stdio.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <string.h> #include <stdlib.h> #define PRINT_ERR(msg) do{\ printf("%s %s %d\n", __FILE__, __func__, __LINE__);\ printf(msg);\ exit(-1); \ }while(0) int main(int argc, char const *argv[]) { key_t key; int shmid; char* over; if ((key = ftok("/home/linux", 'r')) == -1){ PRINT_ERR("ftok error"); } if ((shmid = shmget(key, 4096, IPC_CREAT|0666)) == -1){ PRINT_ERR("shmget error\n"); } if ((over = shmat(shmid, NULL, 0)) == (void*)-1){ PRINT_ERR("shmat error\n"); } while (1){ printf("請(qǐng)輸入>>"); fgets(over,4096,stdin); over[strlen(over) - 1] = '\0'; if (!strncmp("quit",over,4)){ break; } } if (shmdt(over)){ PRINT_ERR("shmdt error\n"); } shmctl(shmid,IPC_RMID,NULL); return 0; }
4.5信號(hào)燈集合
信號(hào)量的原理
信號(hào)量:又叫信號(hào)燈集,它是實(shí)現(xiàn)進(jìn)程間同步的機(jī)制。在一個(gè)信號(hào)燈集中可以有很多的信號(hào)燈,這些信號(hào)燈它們的工作相關(guān)不干擾。一般使用的時(shí)候使用的是二值信號(hào)燈。
信號(hào)燈集函數(shù)的封裝
sem.h
#ifndef __SEM_H__ #define __SEM_H__ int mysem_init(int nsems); int P(int semid, int semnum); int V(int semid, int semnum); int sem_del(int semid); #endif sem.c #include <head.h> union semun { int val; /* Value for SETVAL */ struct semid_ds* buf; /* Buffer for IPC_STAT, IPC_SET */ }; int semnum_init_value(int semid, int which, int value) { union semun sem = { .val = value, }; if (semctl(semid, which, SETVAL, sem) == -1) PRINT_ERR("semctl int value error"); return 0; } //初始化信號(hào)燈集 int mysem_init(int nsems) { key_t key; int semid; // 1.通過(guò)ftok獲取鍵值 if ((key = ftok("/home/linux/", 'g')) == -1) PRINT_ERR("get key error"); // 2.如果不選擇就創(chuàng)建信號(hào)燈集,如果存在返回已存在的錯(cuò)誤 if ((semid = semget(key, nsems, IPC_CREAT | IPC_EXCL | 0666)) == -1) { if (errno == EEXIST) { //如果已存在,這里調(diào)用semget,直接返回semid semid = semget(key, nsems, IPC_CREAT | 0666); } else { PRINT_ERR("create sem error"); } } else { // 3.初始化信號(hào)燈集中的信號(hào)燈 for (int i = 0; i < nsems; i++) { semnum_init_value(semid, i, !i); } } return semid; } //申請(qǐng)資源 int P(int semid, int semnum) { struct sembuf buf = { .sem_num = semnum, .sem_op = -1, .sem_flg = 0, }; if (semop(semid, &buf, 1)) PRINT_ERR("request resource error"); return 0; } //釋放資源 int V(int semid, int semnum) { struct sembuf buf = { .sem_num = semnum, .sem_op = 1, .sem_flg = 0, }; if (semop(semid, &buf, 1)) PRINT_ERR("free resource error"); return 0; } //刪除信號(hào)燈集 int sem_del(int semid) { semctl(semid,0,IPC_RMID); }
用信號(hào)燈集實(shí)現(xiàn)進(jìn)程同步
寫(xiě)端:
#include <head.h> #include "sem.h" int main(int argc, const char* argv[]) { key_t key; int shmid,semid; char* waddr; //0.信號(hào)量的初始化 semid = mysem_init(2); if(semid == -1){ printf("sem init error"); return -1; } // 1.獲取key if ((key = ftok("/home/linux", 'p')) == -1) PRINT_ERR("get key error"); // 2.創(chuàng)建共享內(nèi)存 if ((shmid = shmget(key, 4096, IPC_CREAT | 0666)) == -1) PRINT_ERR("create share memory error"); // 3.將共享內(nèi)存映射到用戶(hù)空間 if ((waddr = shmat(shmid, NULL, 0)) == (void*)-1) PRINT_ERR("shmat error"); printf("waddr = %p\n", waddr); // 4.寫(xiě)操作 while (1) { P(semid,0); printf("input > "); fgets(waddr, 4096, stdin); waddr[strlen(waddr) - 1] = '\0'; if (strncmp(waddr, "quit", 4) == 0) break; V(semid,1); } // 5.取消地址映射 if (shmdt(waddr)) PRINT_ERR("shmdt error"); // 6.刪除共享內(nèi)存 if (shmctl(shmid, IPC_RMID, NULL)) PRINT_ERR("shmrm error"); //7.刪除信號(hào)量 sem_del(semid); return 0; }
讀端口:
#include "sem.h" #include <head.h> int main(int argc, const char* argv[]) { key_t key; int shmid, semid; char* raddr; // 0.信號(hào)量的初始化 semid = mysem_init(2); if (semid == -1) { printf("sem init error"); return -1; } // 1.獲取key if ((key = ftok("/home/linux", 'p')) == -1) PRINT_ERR("get key error"); // 2.創(chuàng)建共享內(nèi)存 if ((shmid = shmget(key, 4096, IPC_CREAT | 0666)) == -1) PRINT_ERR("create share memory error"); // 3.將共享內(nèi)存映射到用戶(hù)空間 if ((raddr = shmat(shmid, NULL, 0)) == (void*)-1) PRINT_ERR("shmat error"); printf("waddr = %p\n", raddr); // 4.讀操作 while (1) { P(semid,1); printf("raddr = %s\n", raddr); if (strncmp(raddr, "quit", 4) == 0) break; V(semid,0); } // 5.取消地址映射 if (shmdt(raddr)) PRINT_ERR("shmdt error"); // 6.刪除共享內(nèi)存 shmctl(shmid, IPC_RMID, NULL); //7.刪除信號(hào)量 sem_del(semid); return 0; }
以上就是C語(yǔ)言中進(jìn)程間通訊的方式詳解的詳細(xì)內(nèi)容,更多關(guān)于C語(yǔ)言進(jìn)程通訊的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- C語(yǔ)言進(jìn)程程序替換的實(shí)現(xiàn)詳解
- C語(yǔ)言超詳細(xì)分析多進(jìn)程的概念與使用
- 詳解C語(yǔ)言進(jìn)程同步機(jī)制
- C語(yǔ)言實(shí)現(xiàn)進(jìn)程間通信原理解析
- C語(yǔ)言實(shí)現(xiàn)查看進(jìn)程是否存在的方法示例
- C語(yǔ)言中查詢(xún)進(jìn)程信號(hào)是否被遮罩或擱置的簡(jiǎn)單方法
- C語(yǔ)言中進(jìn)程信號(hào)集的相關(guān)操作函數(shù)詳解
- C語(yǔ)言中操作進(jìn)程信號(hào)的相關(guān)函數(shù)使用詳解
- C語(yǔ)言控制進(jìn)程之進(jìn)程等待詳解
相關(guān)文章
Matlab利用遺傳算法GA求解非連續(xù)函數(shù)問(wèn)題詳解
遺傳算法起源于對(duì)生物系統(tǒng)所進(jìn)行的計(jì)算機(jī)模擬研究。其本質(zhì)是一種高效、并行、全局搜索的方法,能在搜索過(guò)程中自動(dòng)獲取和積累有關(guān)搜索空間的知識(shí),并自適應(yīng)地控制搜索過(guò)程以求得最佳解。本文將利用其求解非連續(xù)函數(shù)問(wèn)題,需要的可以參考一下2022-09-09C語(yǔ)言使用rand函數(shù)生成隨機(jī)數(shù)
這篇文章介紹了C語(yǔ)言使用rand函數(shù)生成隨機(jī)數(shù)的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12使用Visual Studio 2010/2013編譯V8引擎步驟分享
這篇文章主要介紹了使用Visual Studio 2013編譯V8引擎步驟分享,需要的朋友可以參考下2015-08-08解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題
今天小編就為大家分享一篇解決codeblocks斷點(diǎn)不停無(wú)效的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-12-12Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例
本文主要介紹了Qt編寫(xiě)地圖遷徙圖的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12