系統(tǒng)編程--進(jìn)程間通信

四種方式

  • 管道(僅有血緣關(guān)系的使用)
  • 信號 (開銷小)
  • 套接字
  • 共享映射區(qū)

一裂垦、管道

linux下文件類型共七種:
普通顺囊,目錄,軟鏈接
字符缸废,塊包蓝,管道,套接字-----偽文件企量,不占用磁盤测萎,僅占用內(nèi)存緩沖區(qū)。

管道需要保證單向流通届巩,不能有第三方連通管道


1.1 管道的特點

  • 由兩個文件描述符引用硅瞧,一個表示讀,一個表示寫
  • 規(guī)定數(shù)據(jù)從寫端流向讀端
  • 由環(huán)形隊列實現(xiàn)恕汇,借助內(nèi)存緩沖區(qū)(大小4k)腕唧,因此讀取后就消失
  • 無論匿名還是有名,讀取之后數(shù)據(jù)就會消失

弊端

  • 不能自己讀自己寫
  • 每個數(shù)據(jù)只能讀取一次
  • 半雙工通信瘾英,單向流動
  • 只能在有公公祖先的進(jìn)程使用管道

1.2 PIPE()

int pipe(int pipefd[2])
//參數(shù)fd[0]讀端     fd[1]寫端
//成功返回0枣接,失敗-1

例子

int fd[2];
pipe(fd);
pid_t pid=fork();
char buf[1024];
//每個進(jìn)程都有讀寫兩端連接管道
if(pid>0){
close(fd[0]);//關(guān)閉讀
write(fd[1],"hello",strlen("hello"));//父親寫
close(fd[1]);

}
else{
close(fd[1]);//關(guān)閉寫
ret=read(fd[0],buff,sizof(buff));//兒子讀
}

1.3 管道讀寫行為


如果管道中無數(shù)據(jù)

  • 若寫端全部關(guān)閉,read返回0缺谴;
  • 若寫端未關(guān)閉但惶,則阻塞(讓出cpu)


如果讀端關(guān)閉,則異常終止

如果讀端未關(guān)閉

  • 管道已滿,write阻塞
  • 未滿膀曾,正常讀寫

1.4 有名管道FIFO(創(chuàng)建管道文件)

//命令行
mkfifo filename

#include<sys/stat.h>
//庫函數(shù)县爬,man 3 mkfifo

int mkfifo(char * filename,mode_t mode);

1.4.1 實例,搭配sprintf使用

用sprintf將要寫的數(shù)據(jù)存儲

//1.創(chuàng)建fifo文件添谊,mkfifo myfifo
//2.編寫兩個.c文件财喳,相當(dāng)于兩個無血緣關(guān)系的進(jìn)程
//fifo_w:
char buf[4096];
int fd=open("myfifo",O_WRONLY);
while(1){
sprintf(buf,"hello fifo %d\n",i++);
write(fd,buf,strlen(buf));
sleep(1);
}


//fifo_r:
char buf[4096];
int fd=open("myfifo",O_RDONLY);
while(1){
len=read(fd,buf,sizeof(buf));
write(STDOUT_FILENO,buf,len);
sleep(1);
}


二、存儲映射mmap

將磁盤映射到內(nèi)存,即可以通過指針來操作文件斩狱,操作的目標(biāo)還是文件所以可以無血緣通信

/*
void*指任意返回類型耳高,用任何指針都可以

addr:一般填NULL,表示系統(tǒng)自己分配映射地址
length:<文件大小所踊,否則會出總線錯誤
prot:共享映射區(qū)讀寫屬性 PROT_READ祝高、PROT_WRITE、PROT_READ | PROT_WRITE
flags:標(biāo)注共享內(nèi)存屬性 MAP_SHARED污筷、MAP_RIVATE
offset:偏移位置,需要是4k的整數(shù)倍
return:映射的首地址
              MAP_FAILED.errno

*/
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

案例

char * c=mmap(xxxxx);
strcpy(c,"hello");

2.1 munmap

int munmap(void *addr, size_t len);
//釋放映射區(qū) 

2.2 mmap保險調(diào)用方式

  • fd=open(文件名, O_RDWR);
  • mmap(NULL,有效文件大小, PROT_READ|PROT_WRITE, MAP_SHARED, fd,0);

2.3 mmap父子間通信

        int fd=open("mmap.txt",O_CREAT|O_RDWR,0644);
        ftruncate(fd,50);
        int len=lseek(fd,0,SEEK_END);
        char * p=mmap(NULL,len,PROT_READ|PROT_WRITE, MAP_SHARED, fd,0);

         if(p==MAP_FAILED){
               perror("mmap error");
                  exit(1);
          }
          pid=fork();

          if(pid==0){
            strcpy(p,"i am child");
          }else{
            sleep(1);
            strcpy(p+strlen(p),"i am father");
            printf("%s",p);
            wait(NULL);
       }

通過讀寫同一個指針乍赫,來進(jìn)行通信

2.3 mmap無血緣通信

//兩個文件瓣蛀,一個讀一個寫,mmap_w,mmap_r
//mmap_w同上
//mmap_r:
   int fd=open("mmap.txt",O_RDONLY,0644);
   int len=lseek(fd,0,SEEK_END);
   char * p=mmap(NULL,len,PROT_READ|PROT_WRITE, MAP_SHARED, fd,0);
    printf("%s",p);

mmap內(nèi)部數(shù)據(jù)可以多次讀取雷厂,fifo不行

三惋增、信號

信號產(chǎn)生和處理都是由內(nèi)核操作
阻塞信號集:對此集合信號設(shè)置屏蔽,當(dāng)屏蔽x信號之后改鲫,再收到該信號诈皿,就對該信號進(jìn)行處理推后()
未決信號集:未處理的信號

3.1 信號的處理方式

  • 執(zhí)行默認(rèn)動作
  • 忽略
  • 捕捉(執(zhí)行用戶處理函數(shù))

3.2 信號四要素

  • 名稱
  • 編號
  • 信號對應(yīng)事件
  • 信號默認(rèn)處理動作

3.3 常規(guī)信號

  1. SIGHUP: 當(dāng)用戶退出shell時,由該shell啟動的所有進(jìn)程將收到這個信號像棘,默認(rèn)動作為終止進(jìn)程稽亏。
  2. SIGINT:當(dāng)用戶按下了<ctr+C>組合鍵時,用戶終端向正在運行中的由該終端啟動的程序發(fā)出此信號缕题。默認(rèn)動作為終止進(jìn)程
  3. SIGQUIT:當(dāng)用戶按下<ctrI+\>組合鍵時產(chǎn)生該信號截歉,用戶終端向正在運行中的由該終端啟動的程序發(fā)出些信號。默認(rèn)動作為終止進(jìn)程
  4. SIGILL:CPU檢測到基進(jìn)程執(zhí)行了非法指令烟零。默認(rèn)動作為終止進(jìn)程并產(chǎn)生core文件瘪松。
  5. SIGTRAP:該信號由斷點指令或其他trap指令產(chǎn)生。默認(rèn)動作為終止里程并產(chǎn)生core文件锨阿。
  6. SIGABRT:調(diào)用abort函數(shù)時產(chǎn)生該信號宵睦。默認(rèn)動作為終止進(jìn)程并產(chǎn)生core文件。
  7. SIGBUS:非法訪問內(nèi)存地址墅诡,包括內(nèi)存對齊出錯壳嚎,默認(rèn)動作為終止進(jìn)程并產(chǎn)生core文件。
  8. SIGFPE:在發(fā)生致命的運算錯誤時發(fā)出。不僅包括浮點運算錯誤诬辈,還包括溢出及除數(shù)為0等所有的算法錯誤酵使。默認(rèn)動作為終止進(jìn)程并產(chǎn)生core文件
  9. SIGKILL:無條件終止進(jìn)程。本信號不能被忽略焙糟,處理和阻塞口渔。默認(rèn)動作為終止進(jìn)程。它向系統(tǒng)管理員提供了可以殺死任何進(jìn)程的方法穿撮。
  10. SIGUSR1:用戶定義的信號缺脉。即程序員可以在程序中定義并使用該信號。默認(rèn)動作為終止進(jìn)程悦穿。
  11. SIGSEGV:指示進(jìn)程進(jìn)行了無效內(nèi)存訪問攻礼。默認(rèn)動作為終止進(jìn)程并產(chǎn)生core文件。
  12. SIGUSR2:另外一個用戶自定義信號栗柒,程序員可以在程序中定義并使用該信號礁扮。默認(rèn)動作為終止進(jìn)程。
  13. SIGPIPE::Broken pipe向一個沒有讀端的管道寫數(shù)據(jù)瞬沦。默認(rèn)動作為終止進(jìn)程太伊。
  14. SIGALRM:定時器超時,超時的時間由系統(tǒng)調(diào)用alarm設(shè)置逛钻。默認(rèn)動作為終止進(jìn)程僚焦。
  15. SIGTERM:程序結(jié)束信號,與SIGKILL不同的是曙痘,該信號可以被陽塞和終止芳悲。通常用來要示程序正常退出。執(zhí)行shell命令Kll時边坤,缺省產(chǎn)生這個信號名扛。默認(rèn)動作為終止進(jìn)程。
  16. SIGSTKFLT: Linux 早期版本出現(xiàn)的信號茧痒,現(xiàn)仍保留向后兼容罢洲。**默認(rèn)動作為終止進(jìn)程。(不用)
  17. SIGCHLD:子進(jìn)程狀態(tài)發(fā)生變化時文黎,父進(jìn)程會收到這個信號惹苗。默認(rèn)動作為忽略這個信號。
  18. SIGCONT:如果進(jìn)程已停止耸峭,則使其繼續(xù)運行桩蓉。默認(rèn)動作為繼續(xù)/忽略。
  19. SIGSTOP:停止進(jìn)程的執(zhí)行劳闹。信號不能被忽略院究,處理和阻塞洽瞬。默認(rèn)動作為暫停進(jìn)程。
  20. SIGTSTP:停止終端交互進(jìn)程的運行业汰。按下<ctrl+z>組合鍵時發(fā)出這個信號伙窃。默認(rèn)動作為暫停進(jìn)程。

3.4 alarm

設(shè)置定時器样漆,結(jié)束后向進(jìn)程發(fā)送SIGALARM为障,結(jié)束進(jìn)程,返回0或者剩余時長放祟,
重新調(diào)用alarm會打斷當(dāng)前鳍怨,返回剩余時間。
因此暫停alarm使用alarm(0);

int alarm(int seconds);


3.5 信號集的操作(未決跪妥,阻塞)

3.5.1 信號集的設(shè)置

sigset_t set;     //設(shè)置信號集

int sigemptyset(sigset_t * set);    //清空信號集
int sigfillset(sigset_t * set);    //將信號集全部置1
int sigaddset(sigset_t * set,int signum);      //將某個信號加入信號集 1
int sigdelset(sigset_t *set,int signum)     //將某個信號清出信號集 0
int sigismember(const sigset_t *set, int signum);    //判斷某個信號是否在信號集

3.5.2 sigprocmask

設(shè)置阻塞信號集

 int sigprocmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
//
/*
how的取值
SIG_BLOCK    設(shè)置阻塞
SIG_UNBLOCK    取消阻塞
SIG_SETMASK    用自定義mask替換set

oldset:傳出參數(shù)鞋喇,舊有的mask
*/

3.5.3 sigpending

查看未決信號集

int sigpending(sigset_t *set);
//set 傳出參數(shù),查看未決信號集

案例

//設(shè)置ctrl c阻斷
sigset_t set,oldset,tempset;
sigemptyset(&set);
sigaddset(&set,SIGINT);
int ret=sigprocmask(SIG_BLOCK,&set眉撵,&oldset);
sigpending(&tempset);
for(int i=1;i<32;i++)
  if(sigismember(set,i))
          putchar(1);
else
          putchar(0);

3.6 信號捕捉

注冊一個信號捕捉函數(shù)

#include<signal.h>
//該操作又signal和sigaction函數(shù)
 signal(int sig, sig_t func);

 int sigaction(int sig, const struct sigaction * act, struct sigaction * oact);

3.7 信號回收子進(jìn)程

3.7.1 SIGCHILD

產(chǎn)生條件:子進(jìn)程狀態(tài)發(fā)生變動侦香,包括終止暫停等

void catch_child(int signo){
     wait(NULL);
     return;
  }
 
父進(jìn)程執(zhí)行:
struct sigaction act;
act.sa_handler=catch_child;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
sigaction(SIGCHLD,&act,NULL);

四纽疟、本地套接字

兩通信者鄙皇,互相創(chuàng)建兩個socket,通過socket連接建立通信

server.c

int lfd=socket(AF_UNIX,SOCK_STREAM / SOCK_DGRAM,0);
struct sockaddr_un addr;
/*
struct sockaddr_un{
_kernel_sa_family_t sun_family;      //AF_UNIX
char sun_path[UNIX_PATH_MAX];      //socket文件名
};
*/
strcpy(addr.sun_path,"srv.socket");
int len=offsetof(struct sockaddr_un,sun_path)+strlen("srv.socket");
unlink("srv.socket");
bind(fd,(struct sockaddr*)&addr,len);//bind函數(shù)調(diào)用成功時仰挣,會創(chuàng)建一個socket,為了保證創(chuàng)建成功缠沈,在bind之前會調(diào)用unlink
listen(lfd,28);


while(1){
socklen_t clen=sizeof(caddr);
accept(lfd,(struct sockaddr*)&caddr,&len);
}

client.c

int cfd=socket(AF_UNIX,SOCK_STREAM / SOCK_DGRAM,0);
struct sockaddr_un caddr,saddr;
/*
struct sockaddr_un{
_kernel_sa_family_t sun_family;      //AF_UNIX
char sun_path[UNIX_PATH_MAX];      //socket文件名
};
*/
strcpy(caddr.sun_path,"clie.socket");
int len=offsetof(struct sockaddr_un,sun_path)+strlen("clie.socket");
unlink("clie.socket");
bind(fd,(struct sockaddr*)&addr,len);

saddr.sun_family=AF_UNIX;
strcpy(saddr.sun_path,"srv.socket");
int len=offsetof(struct sockaddr_un,sun_path)+strlen("srv.socket");
connect(cfd,(struct sockaddr*)&saddr,len); 
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末膘壶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子洲愤,更是在濱河造成了極大的恐慌颓芭,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件柬赐,死亡現(xiàn)場離奇詭異亡问,居然都是意外死亡,警方通過查閱死者的電腦和手機肛宋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門州藕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人酝陈,你說我怎么就攤上這事床玻。” “怎么了沉帮?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵锈死,是天一觀的道長贫堰。 經(jīng)常有香客問我,道長待牵,這世上最難降的妖魔是什么其屏? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮缨该,結(jié)果婚禮上偎行,老公的妹妹穿的比我還像新娘。我一直安慰自己压彭,他們只是感情好睦优,可當(dāng)我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著壮不,像睡著了一般汗盘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上询一,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天隐孽,我揣著相機與錄音,去河邊找鬼健蕊。 笑死菱阵,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的缩功。 我是一名探鬼主播晴及,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼嫡锌!你這毒婦竟也來了虑稼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤势木,失蹤者是張志新(化名)和其女友劉穎蛛倦,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體啦桌,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡溯壶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了甫男。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片且改。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖板驳,靈堂內(nèi)的尸體忽然破棺而出钾虐,到底是詐尸還是另有隱情,我是刑警寧澤笋庄,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布效扫,位于F島的核電站倔监,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏菌仁。R本人自食惡果不足惜浩习,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望济丘。 院中可真熱鬧谱秽,春花似錦、人聲如沸摹迷。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽峡碉。三九已至近哟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間鲫寄,已是汗流浹背吉执。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留地来,地道東北人戳玫。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像未斑,于是被迫代替她去往敵國和親咕宿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,843評論 2 354