一、无名管道
无名管道是半双工的,对于一个管道来说,只能读或者写。
无名管道只能在相关的、有共同祖先的进程间使用。(一个fork或exec调用创建的子进程继承了父进程的文件描述符)
读写管道与读写普通文件方式一样,管道用来交换数据,不能对一个管道的两端进行读写操作。
//读写无名管道的例子
int main(void)
{
int fd[2]; //管道描述符
char buf[100]; //存放管道收发的数据
int len; //记录长度
pipe(fd);
memset(buf,0,sizeof(buf));//清空buf
int pid = fork();
if(pid == 0)
{
close(fd[1]);//关闭第二个管道
while((len = read(fd[0],buf,sizeof(buf))) > 0)//循环读取第一个管道
{
write(STDOUT_FILENO,buf,len);
}
close(fd[0]);
}else
{
close(fd[0]);//关闭第一个管道
strcpy(buf, "helloworld\n");
write(fd[1],buf,sizeof(buf)); //写第二个管道
close(fd[1]);
waitpid(pid,NULL,0);//等待子进程退出
}
return EXIT_SUCCESS;
}
二、有名管道(FIFO)
有名管道是持久稳定的,存在于文件系统中。FIFO能让无关联的进程之间交换数据。
一个shell命令能建立一个有名管道。
mkfifo [option] name
创建一个名为name的有名管道。
例1:
mkfifo fifo1
cat < fifo1 通过cat命令从fifo1中读取数据
新打开复制的终端,输入下一条命令:
ls > fifo1 将ls命令输出的结果写入fifo1中
问题是:
用Xshell的“复制SSH渠道”时,提示 -bash: fifo1: 被中断的系统调用。
而用Xshell的“复制”,则正确,即原终端读取到内容。 Why?(有读者知道的话,求解答)
例2:
mkfifo(“fifo1”,666); //创建管道的函数,八进制数666转化为二进制数110110110,代表读写权限为 rw-rw-rw-
例3:读fifo
int main(void) {
int len = 0;
char buf[100]; //定义一个buf
memset(buf,0,sizeof(buf)); //初始化
int fd = open("fifo1",O_RDONLY); //用只读方式打开fifo1
while((len = read(fd,buf,sizeof(buf))) > 0) //循环从fifo1读取数据,直到fifo1被关闭,循环break
{
printf("%s\n", buf);
}
close(fd);
return 0;
}
例4:写fifo
int main(void) {
char buf[100];
memset(buf,0,sizeof(buf));
int fd = open("fifo1",O_WRONLY); //用只写方式打开fifo1
while(1)
{
scanf("%s",buf); //循环等待用户输入
if(buf[0] == '0') //如果用户输入字符0,退出循环
break;
write(fd, buf, sizeof(buf));//将用户从键盘输入的字符通过fifo1发送出去
}
close(fd);
return 0;
}
例5:实现一个单向聊天
读fifo的代码同例3(只需把printf("%s\n", buf);中的\n去掉)
写fifo的代码如下:
int main(void) {
char buf[100];
memset(buf,0,sizeof(buf));
int fd = open("fifo1",O_WRONLY); //用只写方式打开fifo1
while(1)
{
read(STDIN_FILENO,buf, sizeof(buf)); //循环等待用户输入
if(buf[0] == '0') //如果用户输入字符0,退出循环
break;
write(fd, buf, sizeof(buf));//将用户从键盘输入的字符通过fifo1发送出去
memset(buf, 0, sizeof(buf));
}
close(fd);
return 0;
}
三、共享内存
共享内存是由内核出于在多个进程间交换信息的目的而留出的一块内存区(段)。
int main(void) {
int shmid = shmget(IPC_PRIVATE,1024,0666);//创建共享内存
if(shmid < 0)
printf("error\n");
else
printf("success\n");
return 0;
}
创建成功后,用ipcs –m 命令查看。
如何挂载一个共享内存,代码例子如下:
int main(int arg, char *args[]) {
char *shmbuf;
int shmid = 0;
if(arg > 1)
{
shmid = atoi(args[1]); //通过命令行传递共享内存id号
shmbuf = shmat(shmid, 0, 0);
sleep(60);
shmdt(shmbuf);
}
return 0;
}