Unix進(jìn)程間通信(IPC)
IPC概念:
進(jìn)程間通信(IPC削锰,Inter-Process Communication),指至少兩個(gè)進(jìn)程或線程間傳送數(shù)據(jù)或信號(hào)的一些技術(shù)或方法毕莱。進(jìn)程是計(jì)算機(jī)系統(tǒng)分配資源的最小單位(嚴(yán)格說(shuō)來(lái)是線程)器贩。每個(gè)進(jìn)程都有自己的一部分獨(dú)立的系統(tǒng)資源,彼此是隔離的朋截。為了能使不同的進(jìn)程互相訪問(wèn)資源并進(jìn)行協(xié)調(diào)工作蛹稍,才有了進(jìn)程間通信。舉一個(gè)典型的例子部服,使用進(jìn)程間通信的兩個(gè)應(yīng)用可以被分類為客戶端和服務(wù)器(見(jiàn)主從式架構(gòu))唆姐,客戶端進(jìn)程請(qǐng)求數(shù)據(jù),服務(wù)端回復(fù)客戶端的數(shù)據(jù)請(qǐng)求廓八。有一些應(yīng)用本身既是服務(wù)器又是客戶端奉芦,這在分布式計(jì)算中胆描,時(shí)常可以見(jiàn)到仗阅。這些進(jìn)程可以運(yùn)行在同一計(jì)算機(jī)上或網(wǎng)絡(luò)連接的不同計(jì)算機(jī)上昌讲。
進(jìn)程間通信技術(shù)包括消息傳遞、同步减噪、共享內(nèi)存和遠(yuǎn)程過(guò)程調(diào)用短绸。IPC是一種標(biāo)準(zhǔn)的Unix通信機(jī)制。
使用IPC 的理由:
- 信息共享:Web服務(wù)器筹裕,通過(guò)網(wǎng)頁(yè)瀏覽器使用進(jìn)程間通信來(lái)共享web文件(網(wǎng)頁(yè)等)和多媒體醋闭;
- 加速:維基百科使用通過(guò)進(jìn)程間通信進(jìn)行交流的多服務(wù)器來(lái)滿足用戶的請(qǐng)求;
- 模塊化;
- 私有權(quán)分離.
與直接共享內(nèi)存地址空間的多線程編程相比朝卒,IPC的缺點(diǎn):[1]
- 采用了某種形式的內(nèi)核開(kāi)銷证逻,降低了性能;
- 幾乎大部分IPC都不是程序設(shè)計(jì)的自然擴(kuò)展,往往會(huì)大大地增加程序的復(fù)雜度抗斤。
一囚企、管道
1、特點(diǎn):
管道是一種半雙工的通信方式(即數(shù)據(jù)只能單向流動(dòng))瑞眼,也有部分系統(tǒng)上實(shí)現(xiàn)了全雙工的管道龙宏,出于程序可移植性考慮,建議使用半雙工管道伤疙,全雙工的通信可由其它方式實(shí)現(xiàn)银酗,例如:消息隊(duì)列,Unix域套接字徒像。
-
管道分為兩種黍特,無(wú)名管道和有名管道。
- 無(wú)名管道:
最早出現(xiàn)的管道是沒(méi)有名字的锯蛀,因此只能用于父子進(jìn)程間通信灭衷,父進(jìn)程通過(guò)
fork()
系統(tǒng)調(diào)用創(chuàng)建一個(gè)子進(jìn)程,然后通過(guò)管道通信谬墙。- 有名管道(FIFO):
有名管道也叫FIFO今布,由于磁盤中存在實(shí)際的管道文件,前者沒(méi)有拭抬,所以叫有名管道部默。
FIFO
的意思是(first in ,first out),先進(jìn)先出造虎。FIFO是一個(gè)(單向的)半雙工數(shù)據(jù)流傅蹂,不同于普通管道的是,每個(gè)FIFO都有一個(gè)對(duì)應(yīng)文件的路徑名與之關(guān)聯(lián),因此它能完成多個(gè)無(wú)親緣關(guān)系進(jìn)程之間的通信份蝴。 FIFO和無(wú)名管道的數(shù)據(jù)都存在內(nèi)核的內(nèi)存緩沖區(qū)中犁功,大小一般為一頁(yè)(4K)。不同的是婚夫,F(xiàn)IFO將內(nèi)核緩沖區(qū)的數(shù)據(jù)映射到了實(shí)際的文件節(jié)點(diǎn)浸卦,可以在磁盤中看到對(duì)應(yīng)的文件,所以叫有名管道案糙,而無(wú)名管道在磁盤中沒(méi)有對(duì)應(yīng)文件限嫌,因此稱無(wú)名管道。
無(wú)名管道通過(guò)
<unistd.h>
頭文件中的pipe()
創(chuàng)建时捌,有名管道(FIFO)通過(guò)<sys/stat.h>
中的mkfifo()
創(chuàng)建怒医。管道通過(guò)
read()
和write()
進(jìn)行讀寫(xiě)操作,管道內(nèi)核緩沖區(qū)中的數(shù)據(jù)一旦被取走奢讨,管道中將不存在稚叹。當(dāng)內(nèi)核緩沖區(qū)滿的時(shí)候,write()
寫(xiě)操作將被阻塞拿诸,直到緩沖區(qū)有空閑再繼續(xù)扒袖。同理,當(dāng)緩沖區(qū)數(shù)據(jù)為空時(shí)佳镜,read()
操作將阻塞僚稿,直到有新數(shù)據(jù)時(shí)再返回。當(dāng)進(jìn)程終止時(shí)蟀伸,管道就完全被刪除了。
-
無(wú)名管道
1缅刽、過(guò)程
-
創(chuàng)建管道
#include <unistd.h> pipe(int fd[2])
-
通過(guò)
fork()
創(chuàng)建子進(jìn)程// 返回值 >=0:成功 <0:錯(cuò)誤 // 如果是父進(jìn)程則返回子進(jìn)程 id,子進(jìn)程則返回 0 fork()
read()
和write()
讀寫(xiě)緩沖區(qū)的數(shù)據(jù)
2啊掏、例子
- pipe.c
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd[2]; // 管道描述符
pid_t pid; // 進(jìn)程id
char buff[20]; // 緩沖區(qū)長(zhǎng)度
if(pipe(fd) < 0){
printf("創(chuàng)建管道失敗\n");
}
pid = fork(); // 創(chuàng)建子進(jìn)程
if(pid < 0){
printf("fork()失敗\n");
}else if (pid > 0){ // 大于0為主進(jìn)程
close(fd[0]); // 關(guān)閉主進(jìn)程讀端
write(fd[1],"hello world\n",12);
}else{ // 小于0為子進(jìn)程
close(fd[1]); // 關(guān)閉子進(jìn)程寫(xiě)端
sleep(2);
read(fd[0], buff, 20);
printf("讀到的數(shù)據(jù):%s\n", buff);
}
return 0;
}
-
有名管道FIFO
1、過(guò)程
- 按以下示例衰猛,先運(yùn)行
read_fifo.c
迟蜜,創(chuàng)建管道文件(注意: 此時(shí)管道文件必須不存在,否則會(huì)出錯(cuò))啡省。 - 因?yàn)榇藭r(shí)管道中還沒(méi)有數(shù)據(jù)娜睛,
read()
處于阻塞狀態(tài),等待數(shù)據(jù)卦睹。 - 再運(yùn)行
write_fifo.c
畦戒,向管道中寫(xiě)入數(shù)據(jù),此時(shí)read()
打印write_fifo.c
寫(xiě)入的數(shù)據(jù)结序。
2障斋、例子
- read_fifo.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
int main()
{
int fd,len;
char buff[1024]; //管道緩沖區(qū)大小
if(mkfifo("/Users/meetmax/CWork/fifo1", 0666) < 0)
{ // 創(chuàng)建FIFO管道,此時(shí)`fif01`文件必須不存在,否則報(bào)錯(cuò)
perror("Create FIFO Failed");
exit(1);
}
if((fd = open("/Users/meetmax/CWork/fifo1", O_RDONLY)) < 0)
{ // 以只讀模式打開(kāi)FIFO,和打開(kāi)普通文件一樣
perror("Open FIFO Failed");
exit(1);
}
// 如果管道中有數(shù)據(jù)垃环,讀取FIFO管道
while((len = read(fd, buff, 1024)) > 0)
printf("Read message: %s", buff);
close(fd); // 關(guān)閉FIFO文件
return 0;
}
- write_fifo.c
#include<stdio.h>
#include<stdlib.h> // exit
#include<fcntl.h> // O_WRONLY
#include<sys/stat.h>
#include<time.h> // time
#include <time.h>
int main()
{
int fd;
int n, i;
char buf[1024];
time_t tp;
printf("I am %d process.\n", getpid()); // 說(shuō)明進(jìn)程ID
if((fd = open("/Users/meetmax/CWork/fifo1", O_WRONLY)) < 0)
// 以寫(xiě)打開(kāi)一個(gè)FIFO
{
perror("Open FIFO Failed");
exit(1);
}
for(i=0; i<10; ++i)
{
time(&tp); // 取系統(tǒng)當(dāng)前時(shí)間
n=sprintf(buf,"Process %d's time is %s",getpid(),ctime(&tp));
printf("Send message: %s", buf); // 打印
if(write(fd, buf, n+1) < 0) // 寫(xiě)入到FIFO中
{
perror("Write FIFO Failed");
close(fd);
exit(1);
}
sleep(1); // 休眠1秒
}
close(fd); // 關(guān)閉FIFO文件
return 0;
}
XIS IPC(基于System V 的IPC函數(shù))
除管道外邀层,還有3種IPC的進(jìn)程間的通信,分別為:消息隊(duì)列遂庄、信號(hào)量和共享內(nèi)存寥院。這3個(gè)IPC有兩種實(shí)現(xiàn)方式,分別為基于System V和POSIX的進(jìn)程間通信涛目。
- 維基百科
System V
UNIX系統(tǒng)五[來(lái)源請(qǐng)求](英語(yǔ):UNIX System V)秸谢,是Unix操作系統(tǒng)眾多版本中的一支。它最初由AT&T開(kāi)發(fā)泌绣,在1983年第一次發(fā)布钮追,因此也被稱為AT&T System V。
POSIX
可移植操作系統(tǒng)接口(英語(yǔ):Portable Operating System Interface阿迈,縮寫(xiě)為POSIX)元媚,是IEEE為要在各種UNIX操作系統(tǒng)上運(yùn)行軟件,而定義API的一系列互相關(guān)聯(lián)的標(biāo)準(zhǔn)的總稱苗沧,其正式稱呼為IEEE Std 1003刊棕,而國(guó)際標(biāo)準(zhǔn)名稱為ISO/IEC 9945。
System V 出現(xiàn)比 POSIX 要早待逞,可以說(shuō)POSIX是對(duì)System V的改進(jìn)甥角,POSIX API使用比前者更加簡(jiǎn)單高效,但是為什么兩者仍然同時(shí)存在呢识樱?還是一個(gè)移植性的問(wèn)題嗤无,雖然現(xiàn)在新的程序都基于POSIX標(biāo)準(zhǔn),但是仍然有很多舊的程序使用了基于System V的IPC怜庸,因此兩者都保留了当犯。本文的IPC基于System V的IPC函數(shù)。
二割疾、消息隊(duì)列
1嚎卫、特點(diǎn)
- 消息隊(duì)列是消息的鏈表,存儲(chǔ)在內(nèi)核中宏榕,由消息隊(duì)列標(biāo)識(shí)符標(biāo)識(shí)拓诸。
- 消息隊(duì)列是隨內(nèi)核持續(xù)的,進(jìn)程終止時(shí)麻昼,消息隊(duì)列及其內(nèi)容不會(huì)被刪除奠支,除非內(nèi)核重啟或者調(diào)用
msgctl()
顯式的刪除消息隊(duì)列。 - 消息隊(duì)列沒(méi)有維護(hù)引用計(jì)數(shù)器(打開(kāi)文件有這種計(jì)數(shù)器)涌献,所以隊(duì)列被刪除后胚宦,仍在使用該隊(duì)列的進(jìn)程會(huì)出錯(cuò)返回。
2、過(guò)程
- 先定義消息隊(duì)列結(jié)構(gòu)
struct msg_form
枢劝,每條消息都包含:- 消息隊(duì)列類型:
long
類型的mtype
- 消息數(shù)據(jù):
char *
類型的字符串
- 消息隊(duì)列類型:
- 通過(guò)文件的路徑名和項(xiàng)目ID(0~255之間)井联,調(diào)用
ftok()
獲取IPC,獲取key值您旁。創(chuàng)建XSI IPC
結(jié)構(gòu)都應(yīng)指定一個(gè)鍵烙常,這個(gè)鍵的數(shù)據(jù)類型是系統(tǒng)數(shù)據(jù)類型key_t,通常在頭文件<sys/types.h>
中定義鹤盒。 - 接著調(diào)用
msgget()
函數(shù)蚕脏,使用key作為其中一個(gè)參數(shù),由內(nèi)核將key
變成IPC的標(biāo)識(shí)符侦锯,在這里就是消息隊(duì)列ID驼鞭。 - 拿到IPC標(biāo)識(shí)符后,通過(guò)
msgsnd()
和msgrcv()
分別發(fā)送和接收消息尺碰。
3挣棕、示例
- msg_client.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSG_FILE "/Users/meetmax/CWork/msg_file"
// 消息結(jié)構(gòu)
struct msg_form {
long mtype;
char mtext[256];
};
int main(){
int msqid; // 消息隊(duì)列id
key_t key; // 鍵值
struct msg_form msg;
//獲取key值
if((key = ftok(MSG_FILE,100)) < 0){
perror("獲取key值失敗\n");
exit(0);
}
printf("key 值為: %d",key);
if((msqid = msgget(key,IPC_CREAT|0777)) < 0){
perror("獲取消息隊(duì)列失敗");
exit(0);
}
printf("消息隊(duì)列id: %d \n",msqid);
printf("進(jìn)程id: %d \n",getpid());
msg.mtype = 888; // 設(shè)置消息類型
sprintf(msg.mtext,"hello,I'm client %d\n",getpid());
msgsnd(msqid,&msg,sizeof(msg.mtext),0);
// 獲取777類型的消息
msgrcv(msqid, &msg, 256, 999, 0);
printf("Client: receive msg.mtext is: %s.\n", msg.mtext);
printf("Client: receive msg.mtype is: %ld.\n", msg.mtype);
return 0;
}
- msg_server.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/msg.h>
#include <unistd.h>
#define MSG_FILE "/Users/meetmax/CWork/msg_file"
struct msg_form{
long mtype;
char mtext[256];
};
int main()
{
int msqid;
key_t key;
struct msg_form msg;
//獲取key值
if((key = ftok(MSG_FILE,100)) < 0){
perror("獲取key失敗");
exit(1);
}
//打印key值
printf("key的值為 %d \n",key);
//根據(jù)key值創(chuàng)建消息隊(duì)列
if((msqid = msgget(key,IPC_CREAT|0777)) < 0){
perror("創(chuàng)建消息隊(duì)列失敗");
exit(1);
}
printf("消息隊(duì)列id為 : %d \n",msqid);
printf("進(jìn)程id為 : %d \n",getpid());
while(1)
{
//接受888類型的消息
msgrcv(msqid,&msg,256,888,0);
printf("Server:receive msg.mtext: %s \n",msg.mtext);
printf("Server:receive msg.xxx: %ld \n",msg.mtype);
msg.mtype = 999;
sprintf(msg.mtext,"hello I'm server: %d \n",getpid());
//發(fā)送消息
msgsnd(msqid,&msg,sizeof(msg.mtext),0);
}
return 0;
}
三、信號(hào)量
1亲桥、特點(diǎn)
信號(hào)量類似鎖機(jī)制洛心,能夠使臨界區(qū)內(nèi)的資源在某一時(shí)刻只能被一個(gè)進(jìn)程訪問(wèn)。臨界區(qū)是指多個(gè)進(jìn)程或線程共享的內(nèi)存空間题篷,在訪問(wèn)臨界區(qū)的時(shí)候词身,多個(gè)進(jìn)程操作同一個(gè)資源,此時(shí)就存在競(jìng)態(tài)條件番枚,通常在兩個(gè)進(jìn)程對(duì)同一個(gè)資源寫(xiě)操作時(shí)法严,會(huì)產(chǎn)生結(jié)果不一致的問(wèn)題,因?yàn)槲覀儾恢老到y(tǒng)進(jìn)程何時(shí)切換葫笼,這種情況也很難復(fù)現(xiàn)和調(diào)試渐夸。必須有一種機(jī)制來(lái)保證在同一時(shí)刻只能有一個(gè)進(jìn)程訪問(wèn)臨界區(qū),信號(hào)量就提供了這種機(jī)制渔欢。
信號(hào)量是一種特殊的變量,程序?qū)λ脑L問(wèn)都是原子操作瘟忱,所謂原子操作奥额,即是指不可被中斷的操作,要實(shí)現(xiàn)原子操作單純軟件是不夠的访诱。雖然也能實(shí)現(xiàn)垫挨,但是效率很低,信號(hào)量是一種和硬件緊密結(jié)合的機(jī)制触菜,它不會(huì)被系統(tǒng)進(jìn)程切換和中斷操作打斷九榔。本文以二值信號(hào)量為例子,二值信號(hào)量能實(shí)現(xiàn)互斥鎖的功能,保證同一時(shí)間只能一個(gè)進(jìn)程訪問(wèn)資源哲泊。
-
信號(hào)量的P,V操作
來(lái)自維基百科
計(jì)數(shù)信號(hào)量具備兩種操作動(dòng)作剩蟀,之前稱為 V(又稱signal())與 P(wait())。 V操作會(huì)增加信號(hào)量 S的數(shù)值切威,P操作會(huì)減少它育特。
運(yùn)作方式:
- 初始化,給與它一個(gè)非負(fù)數(shù)的整數(shù)值先朦。
- 運(yùn)行 P(wait())缰冤,信號(hào)量S的值將被減少。企圖進(jìn)入臨界區(qū)塊的進(jìn)程喳魏,需要先運(yùn)行 P(wait())棉浸。當(dāng)信號(hào)量S減為負(fù)值時(shí),進(jìn)程會(huì)被擋住刺彩,不能繼續(xù)迷郑;當(dāng)信號(hào)量S不為負(fù)值時(shí),進(jìn)程可以獲準(zhǔn)進(jìn)入臨界區(qū)塊迂苛。
- 運(yùn)行 V(又稱signal())三热,信號(hào)量S的值會(huì)被增加。結(jié)束離開(kāi)臨界區(qū)塊的進(jìn)程三幻,將會(huì)運(yùn)行 V(又稱signal())就漾。當(dāng)信號(hào)量S不為負(fù)值時(shí),先前被擋住的其他進(jìn)程念搬,將可獲準(zhǔn)進(jìn)入臨界區(qū)塊抑堡。
2、過(guò)程
- 獲取
key
值(同消息隊(duì)列) - 獲取信號(hào)量ID(同消息隊(duì)列)
-
semctl()
函數(shù)初始化信號(hào)量 -
fork()
子進(jìn)程 - 執(zhí)行P,V操作
3朗徊、例子
sem.c 二值信號(hào)量
#include <stdio.h>
#include <stdlib.h>
#include <sys/sem.h> // 信號(hào)量函數(shù)庫(kù)
#include <unistd.h>
#define SEM_FILE "/Users/meetmax/CWork/sem_file" // 信號(hào)量文件
union sem_union //信號(hào)量聯(lián)合
{
int val;
struct semid_ds *buf;
unsigned short *array;
};
//初始化信號(hào)量
int init_sem(int sem_id,int val)
{
union sem_union tmp;
tmp.val = val;
if((semctl(sem_id,0,SETVAL,tmp)) == -1)
{
perror("初始化信號(hào)量失敗");
return -1;
}
return 0;
}
/**
* P操作
* 信號(hào)量大于0時(shí)執(zhí)行 -1 操作首妖,獲取資源
* 若信號(hào)量 <= 0 則掛起等待
*/
int sem_p(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = -1;
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id,&sbuf,1) == -1)
{
perror("p操作失敗");
return -1;
}
return 0;
}
/**
* V操作
* 信號(hào)量 <= 0時(shí)執(zhí)行,+1操作爷恳,釋放資源
* 若信號(hào)量 > 0 時(shí)掛起等待
*/
int sem_v(int sem_id)
{
struct sembuf sbuf;
sbuf.sem_num = 0;
sbuf.sem_op = 1;
sbuf.sem_flg = SEM_UNDO;
if(semop(sem_id,&sbuf,1) == -1)
{
perror("V操作失敗");
return -1;
}
return 0;
}
//刪除信號(hào)量
int sem_del(int sem_id)
{
union sem_union tmp;
if(semctl(sem_id,0,IPC_RMID,tmp) == -1)
{
perror("刪除信號(hào)量失敗");
return -1;
}
return 0;
}
int main()
{
int sem_id;
key_t key;
pid_t pid;
//獲取key值
if((key = ftok(SEM_FILE,100)) == -1)
{
perror("獲取key值失敗");
exit(1);
}
//獲取信號(hào)量id
if((sem_id = semget(key,1,IPC_CREAT|0666)) == -1)
{
perror("信號(hào)量id獲取失敗");
exit(1);
}
//初始化信號(hào)量
init_sem(sem_id,0);
//fork進(jìn)程
if((pid = fork()) == -1)
{
perror("進(jìn)程fork失敗");
exit(1);
}else if(pid == 0){ //子進(jìn)程
printf("我是子進(jìn)程:%d \n",getpid());
sleep(2);
sem_v(sem_id);
}else if(pid > 0){ //父進(jìn)程
sem_p(sem_id);
printf("我是父進(jìn)程:%d \n",getpid());
sem_v(sem_id);
sem_del(sem_id);
}
return 0;
}
四有缆、共享內(nèi)存
1、特點(diǎn)
概念
顧名思義温亲,共享內(nèi)存就是允許兩個(gè)不相關(guān)的進(jìn)程訪問(wèn)同一個(gè)邏輯內(nèi)存棚壁。共享內(nèi)存是在兩個(gè)正在運(yùn)行的進(jìn)程之間共享和傳遞數(shù)據(jù)的一種非常有效的方式。不同進(jìn)程之間共享的內(nèi)存通常安排為同一段物理內(nèi)存栈虚。進(jìn)程可以將同一段共享內(nèi)存連接到它們自己的地址空間中袖外,所有進(jìn)程都可以訪問(wèn)共享內(nèi)存中的地址,就好像它們是由用C語(yǔ)言函數(shù)malloc分配的內(nèi)存一樣魂务。而如果某個(gè)進(jìn)程向共享內(nèi)存寫(xiě)入數(shù)據(jù)曼验,所做的改動(dòng)將立即影響到可以訪問(wèn)同一段共享內(nèi)存的任何其他進(jìn)程泌射。
2、過(guò)程
-
ftko()
獲取key值(同消息隊(duì)列) - 用
shmget()
函數(shù)獲取共享內(nèi)存ID - 進(jìn)程通過(guò)
shmat()
函數(shù)連接共享內(nèi)存 - 訪問(wèn)共享內(nèi)存
3鬓照、示例
shm_server.c 讀數(shù)據(jù)
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <string.h>
#define SHM_FILE "/Users/meetmax/CWork/shm_file"
int main()
{
int shm_id;
key_t key;
char * shm;
struct shmid_ds buf;
// 獲取key
if((key = ftok(SHM_FILE,100)) == -1)
{
perror("獲取key失敗");
exit(0);
}
// 獲取共享內(nèi)存描述符ID
if((shm_id = shmget(key,512,IPC_CREAT|0666)) == -1)
{
perror("獲取共享內(nèi)存id失敗");
exit(0);
}
// 連接共享內(nèi)存
if((int)(shm = (char *)shmat(shm_id,0,0)) == -1)
{
perror("連接共享內(nèi)存失敗");
exit(1);
}
printf("開(kāi)始接收數(shù)據(jù)\n");
// 開(kāi)始忙等熔酷,接收數(shù)據(jù)
while(1)
{
if(strlen(shm) > 0){
printf("收到數(shù)據(jù):%s \n",shm);
sprintf(shm,"");
}
if(strcmp(shm,"r") == 0){
printf("已退出\n");
break;
}
}
// 刪除共享內(nèi)存
shmctl(shm_id,IPC_RMID,&buf);
return 0;
}
sem_client.c 寫(xiě)入數(shù)據(jù)
#include <stdio.h>
#include <stdlib.h>
#include <sys/shm.h>
#define SHM_FILE "/Users/meetmax/CWork/shm_file"
int main()
{
int shm_id;
key_t key;
char * shm;
// 獲取key
if((key = ftok(SHM_FILE,100)) == -1)
{
perror("獲取key失敗");
exit(0);
}
// 獲取共享內(nèi)存id
if((shm_id = shmget(key,512,IPC_CREAT|0666)) == -1)
{
perror("獲取共享內(nèi)存id失敗");
exit(0);
}
// 連接共享內(nèi)存,若不存在則創(chuàng)建
if((int)(shm = (char *)shmat(shm_id,0,0)) == -1)
{
perror("連接共享內(nèi)存失敗");
exit(1);
}
printf("請(qǐng)輸入:");
scanf("%s",shm); // 寫(xiě)入數(shù)據(jù)到共享內(nèi)存
shmdt(shm); // 斷開(kāi)連接
return 0;
}
參考
- 《UNIX環(huán)境高級(jí)編程》
- 《UNIX網(wǎng)絡(luò)編程:卷2》
- 部分來(lái)自互聯(lián)網(wǎng)