關于管道詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3560130.html。
1、管道實現父子進程間通信實例:
/* pipe.c */#include <unistd.h>#include <stdio.h>#include <limits.h>#include <sys/types.h>#include <errno.h>#include <stdlib.h>#define MAXLINE 1024int main(void){ int fd[2], pid; char buf[MAXLINE]; if(pipe(fd) < 0) { perror("pipe error"); exit(1); } if((pid = fork()) < 0) { perror("fork error"); exit(1); } else if(pid == 0) /* child */ { close(fd[1]); /* read from parent */ if(read(fd[0], buf, MAXLINE) < 0) { perror("read error"); exit(1); } PRintf("read from parent: %s/n", buf); } else /* parent */ { close(fd[0]); /* send to child */ if(write(fd[1], "hello, i am your parent", 24) != 24) { perror("write error"); exit(1); } printf("send to child OK!/n"); wait(NULL); }}
編譯運行結果:
2、管道實現父子進程間同步實例:
/* pipe_sync.c */#include <sys/types.h>#include <errno.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#define BUFSIZE 1024int fd1[2], fd2[2];char c;void tell_wait(){ if(pipe(fd1) < 0 || pipe(fd2) < 0) { perror("pipe error"); exit(1); }}void tell_parent(){ if(write(fd1[1], "c", 1) != 1) { perror("write error"); exit(1); }}void wait_parent(){ if(read(fd2[0], &c, 1) != 1) { perror("read error"); exit(1); } if(c != 'p') { printf("wait_parent: invalid data/n"); exit(1); }}void tell_child(){ if(write(fd2[1], "p", 1) != 1) { perror("write error"); exit(1); }}void wait_child(){ if(read(fd1[0], &c, 1) != 1) { perror("read error"); exit(1); } if(c != 'c') { printf("wait_child: invalid data"); exit(1); }}intmain(void){ int pid; tell_wait(); if((pid = fork()) < 0) { perror("fork error"); exit(1); } else if(pid == 0) { printf("child: first/n"); tell_parent(); } else { wait_child(); printf("parent: after child/n"); } return(0);}
編譯運行結果:
二、命名管道(FIFO)
在文件系統中命名管道是以設備特殊文件的形式存在的。
不同的進程可以通過命名管道共享數據。
關于FIFO詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3561632.html。
FIFO實現進程間通信實例:
/**************************** **** FIFO server*************************************/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO "/home/zhu/network/fifo/myfifo"#define OPEN_MODE O_RDONLYintmain(void){ int fifofd; char buf[80];
unlink(FIFO); /* 防止FIFO已存在 */
if(mkfifo(FIFO, 0777) == -1) { perror("mkfifo"); exit(1); } if((fifofd = open(FIFO, OPEN_MODE)) < 0) { perror("open"); exit(1); } read(fifofd, buf, sizeof(buf)); printf("message from client: %s/n", buf); close(fifofd); return(0);}
/**************************** **** FIFO client*************************************/#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <sys/types.h>#include <sys/stat.h>#define FIFO "/home/zhu/network/fifo/myfifo"#define OPEN_MODE O_WRONLYintmain(void){ int fifofd; char s[] = "hello,server!"; if((fifofd = open(FIFO, OPEN_MODE)) < 0) { perror("open"); exit(1); } write(fifofd, s, sizeof(s)); printf("write message: %s/n", s); close(fifofd); return(0);}
編譯成功后,我們首先運行服務器(創建FIFO,等待客戶發來消息,此時FIFO服務器阻塞):
接著我們在另一個終端窗口運行客戶程序,如下圖所示,可以看出客戶端已成功發送,服務器端也成功接收:
三、消息隊列
消息隊列是內核地址空間中的內部鏈表,通過linux內核在各個進程之間傳遞內容。
關于消息隊列詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3561820.html。
消息隊列實現進程間通信實例:
/**********************************MSGQ server*************************************/#include <sys/msg.h>#include <sys/ipc.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#define msqpath "/home/zhu/network/msgqueue/msq"#define proj_id 'b'struct mymesg { long mtype; char mtext[512]; };int main(void){ key_t key; int msqid; struct msqid_ds buf; struct mymesg msg1; msg1.mtype = 1; sprintf(msg1.mtext, "hello"); if((key = ftok(msqpath, proj_id)) < 0) { perror("ftok"); exit(1); } if((msqid = msgget(key, IPC_CREAT)) < 0) { perror("msgget"); exit(1); } if(msgsnd(msqid, &msg1, sizeof(msg1), IPC_NOWAIT) < 0) { perror("msgsnd"); exit(1); } printf(“send message : hello/n”); if(msgctl(msqid, IPC_STAT, &buf) < 0) { perror("msgctl"); exit(1); } printf("message queue # of messages is: %d/n", buf.msg_qnum); return(0); }
/***************************************MSGQ client**************************************/#include <sys/msg.h>#include <sys/ipc.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#define msqpath "/home/zhu/network/msgqueue/msq"#define proj_id 'b'struct mymesg { long mtype; char mtext[512]; };int main(void){ key_t key; int msqid; struct msqid_ds buf; struct mymesg msg1; if((key = ftok(msqpath, proj_id)) < 0) { perror("ftok"); exit(1); } if((msqid = msgget(key, IPC_EXCL)) < 0) { perror("msgget"); exit(1); } if(msgrcv(msqid, &msg1, sizeof(msg1), 0, IPC_NOWAIT) < 0) { perror("msgrcv"); exit(1); } printf("receive message : %s/n", msg1.mtext); if(msgctl(msqid, IPC_STAT, &buf) < 0) { perror("msgctl"); exit(1); } printf("message queue # of messages is: %d/n", buf.msg_qnum); return(0); }
編譯后運行結果如下:
四、信號量
信號量是一種計數器,用來控制對多個進程共享的資源所進行的訪問。它們常常被用作一個鎖機制,在某個進程正在對特定資源進行訪問時,信號量可以防止另一個進程去訪問它。
關于信號量詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3562046.html。
信號量實現資源控制實例:
#include <sys/types.h>#include <linux/sem.h>#include <linux/ipc.h>#include <sys/stat.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#define sempath "/home/zhu/network/semaphore/sem"#define proj_id 'c'intmain(void){ int semid, i; key_t key; union semun sem, getsem; sem.val = 3; if((key = ftok(sempath, proj_id)) < 0) { perror("ftok"); exit(1); } if((semid = semget(key, 1, IPC_CREAT)) < 0) { perror("semget"); exit(1); } semctl(semid, 0, SETVAL, sem); semctl(semid, 0, GETVAL, sem); printf("# of usable semphore: %d/n", sem.val); struct sembuf sops = {0, -1, IPC_NOWAIT}; for(i = 0; i < 4; i++) { printf(“%dth:”,i+1);
fflush(stdout); if(semop(semid, &sops, 1) < 0) { perror("semop"); exit(1); }
printf("ask for one semaphore:success!/n"); } return(0);}
編譯運行結果如下(因為我們把信號量值設置為3,所以第四次資源請求失?。?/p>
注意,在上面的程序中,包含的頭文件#include <linux/sem.h> 和#include <linux/ipc.h>。而不是#include <sys/sem.h> #include <sys/ipc.h>。否則出現“storage of size of 'sem' isn't know”的錯誤。詳細介紹請參考http://hi.baidu.com/yuhongyangcn/item/f52545b33c1b55a1eaba93ac。
關于POSIX信號量詳情可參考http://www.CUOXin.com/nufangrensheng/p/3564306.html。
注意使用POSIX信號量時,除了要包含頭文件<semaphore.h>外,在編譯選項中還有加上-lrt選項,否則出現“undefined reference to”這樣的編譯錯誤。
五、共享內存共享內存是在多個進程之間共享內存區域的一種進程間通信的方式,它是在多個進程間對內存段進行映射的方式實現內存共享的。這是最快的IPC方式。
關于共享內存詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3563712.html。
共享內存實現父子進程間通信(這里為了簡化、突出共享內存的使用方式,并沒有加入同步處理,而只是簡單地使用sleep模擬同步):
#include <stdio.h>#include <sys/types.h>#include <sys/ipc.h>#include <sys/shm.h>#include <string.h>static char msg[] = "hello, share memory!";int main(void){ key_t key; char i, *shms, *shmc; pid_t pid; int shmid; key = ftok("/home/zhu/network/shmm/shm", 'a'); shmid = shmget(key, 1024, IPC_CREAT | 0604); pid = fork(); if( pid > 0) { shms = (char *)shmat(shmid, 0, 0); memcpy(shms, msg, strlen(msg) + 1); sleep(5); shmdt(shms); } else if(pid == 0) { shmc = (char *)shmat(shmid, 0, 0); sleep(2); printf("the content in the share memory is : %s/n", shmc); shmdt(shmc); } return(0);}運行結果:
信號(signal)機制是UNIX系統中最為古老的進程之間的通信機制。它用于在一個或多個進程之間傳遞異步信號。
關于信號詳細介紹可參考http://www.CUOXin.com/nufangrensheng/p/3514157.html。
新聞熱點
疑難解答