程序間通信(IPC)
英文名IPC,因為每個程序各自有不同的使用者位址空間,任何一個程序的全局變量在另一個程序看不到,是以程序之間要交換資料必須通過核心,在核心中開辟一塊緩沖區,程序1把資料從使用者位址空間拷到核心緩沖區,程序2再從核心緩沖區把資料讀走,核心提供的這種機制稱為程序間通信。
管道:
管道是Unix中最古老的程序間通信的形式,是一種最基本的IPC機制。
我們把從一個程序連接配接到另一個程序的資料流稱為一個“管道”。
特點:
(1)隻能用于有公共祖先的程序之間通信。
(2)管道提供流式服務
(3)生命周期随程序
(4)核心會對管道進行同步與互斥
(5)管道是半雙工的,需要雙方通信時,須建立兩個管道。
匿名管道
#include<unistd.h>
int pipe(int fd[]);
//成功傳回0,失敗傳回錯誤代碼
fd[0]為讀而打開,fd[1]為寫而打開
fd[1]的輸出是fd[0]的輸入。
單個程序中的管道幾乎沒有任何用處。管道隻能在具有公共祖先的兩個程序之間使用。通常,一個管道由一個程序建立,在程序調用fork之後,這個管道就能在父程序和子程序之間使用了。
父程序調用pipe開辟管道,得到兩個檔案描述符指向管道的兩端,父程序調用fork建立了子程序,子程序也有兩個檔案描述符指向同一管道。
因為管道是單向通信的,是以父程序關閉寫端,子程序關閉讀端。子程序可以往管道裡寫,父程序可以在管道裡讀。
代碼實作:
#include<stdio.h>
#include<unistd.h>
#include<string.h>
int main()
{
//(1)程序建立管道
int fds[] = {,};
int ret = pipe(fds);
if(ret < )
{
perror("pipe");
return ;
}
//(2)建立子程序
pid_t id = fork();
//父程序關閉寫端,子程序關閉讀端
if( id == )//子程序——>寫
{
close(fds[]);
char* msg = "hello father,I am your child";
while()
{
write(fds[],msg,strlen(msg));
sleep();
}
}
else//父程序——>讀
{
char buf[];
close(fds[]);
while()
{
ssize_t s = read(fds[],buf,sizeof(buf)-);
if(s > )
{
buf[s] = ;
printf("%s\n",buf);
}
}
}
return ;
}
[[email protected] ~]$ ./a.out
hello father,I am your child
hello father,I am your child
hello father,I am your child
hello father,I am your child
命名管道
匿名管道隻能用于有血緣關系的程序。命名管道(FIFO)的提出就突破了管道的限制,它可以以不同的方式方法調用(可以跨平台,跨語言,跨權限),隻要知道命名管道的名字,發送到命名管道的資訊可以被一切擁有指定授權的程式讀取。
建立:
//(1)指令行上建立
$ mkfifo filename
//從程式裡建立
int mkfifo(const char *filename,mode_t mode);//成功傳回0,失敗傳回-1
建立命名管道
int main(int argc, char *argv[])
{
mkfifo("p2",);
return ;
}
#include<stdio.h>
#include<sys/stat.h>
int main()
{
int ret = mkfifo("./myfifo",);
if(ret < )
{
perror("mkfifo");
return ;
}
printf("mkfifo ok\n");
return ;
}
[a@localhost ~]$ gcc fifo.c
[a@localhost ~]$ ./a.out
mkfifo ok
用命名管道實作server&client通信
server.c
client.c
makefile
結果: