操作系统:进程通信

一、进程管道
1.读管道
(1)代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
    
    
FILE *read_fp; 
char buffer[BUFSIZ+1]; 
int chars_read;
memset(buffer,‘\0,sizeof(buffer)); 
read_fp=popen(“uname -a”,“r”); 
if(read_fp!=NULL){
    
    
chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp); 
if(chars_read>0) printf(“Output was:-\n%s\n”,buffer);
pclose(read_fp); 
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
2.写管道
(1)代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
    
    
FILE *write_fp;   //文件流指针
char buffer[BUFSIZ+1];    //缓冲区
sprintf(buffer,"Once upon a time, there was...\n");
write_fp=popen("wc -w","w");
if(write_fp!=NULL){
    
    
fwrite(buffer,sizeof(char),strlen(buffer),write_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
二、匿名管道
通过 pipe 函数创建匿名管道,在两个进程间传递数据,而不需要启动一个 shell 来解释请求的命令。该管道工作在更底层,访问管道,使用文件描述符而不是文件流,所以使用系统调用 read 和 write 来访问管道数据。
1.生产者/消费者的管道模型
(1)代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
    
    
int data_processed;
int file_pipes[2]; 
const char some_data[]="123";
char buffer[BUFSIZ+1]; //缓冲区
memset(buffer,'\0',sizeof(buffer)); //初始化缓冲区
if(pipe(file_pipes)==0){
    
     
data_processed= write(file_pipes[1],some_data,strlen(some_data)); 
printf("Wrote %d bytes\n",data_processed);
data_processed=read(file_pipes[0],buffer,BUFSIZ); 
printf("Read %d bytes: %s\n",data_processed,buffer);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
2.父子进程通过管道通信
(1)代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(){
    
    
int data_processed;
int file_pipes[2]; 
const char some_data[]="123";
char buffer[BUFSIZ+1];
pid_t pid;
 memset(buffer,'\0',sizeof(buffer));
if(pipe(file_pipes)==0){
    
     //同上
pid=fork(); //创建子进程
if(pid == -1){
    
    
fprintf(stderr,"Fork failure");
exit(EXIT_FAILURE);
}
if(pid==0){
    
     //子进程并发执行
data_processed=read(file_pipes[0],buffer, BUFSIZ); //读管道
printf("Read %d bytes: %s\n", data_processed,buffer);
exit(EXIT_SUCCESS);
}
else{
    
     //父进程并发执行
data_processed=write(file_pipes[1], some_data, strlen(some_data));
printf("Wrote %d bytes\n",data_processed);
}
}
exit(EXIT_SUCCESS);
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
3.利用信号量实现父子同步通信
(1)代码:

#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
void err_printf(char *p)
{
    
    
    printf("%s\n",p);
    exit(0);
}
int main(void)
{
    
    
        int fd1[2],fd2[2];
        pid_t pid;
        char *str="the data from parent process.\n";
        char *dtr="the data from child process.\n";
        char buf[1024];
        if(pipe(fd1)<0)
                err_printf("pipe fd1 fail");
        if(pipe(fd2)<0)
                err_printf("pipe fd2 fail");
        if((pid=fork())<0)
                err_printf("fork fail");
        else if(pid==0)
        {
    
           
                close(fd1[1]);
                close(fd2[0]);
                //子进程读取数据
                int num=read(fd1[0],buf,sizeof(buf));
                //在终端打印
                write(STDOUT_FILENO,buf,num);
                puts("child recevied the parent message\n");
                //子进程向父进程写东西
                write(fd2[1],dtr,strlen(dtr)+1);
          }
          else
          {
    
    
                close(fd1[0]);
                close(fd2[1]);
                write(fd1[1],str,strlen(str)+1);
                int num=read(fd2[0],buf,sizeof(buf));
                puts("parent recevied the child message\n");
                write(STDOUT_FILENO,buf,num);
           }
            exit(0);
            return 0;
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
三、命名管道 FIFO(常用在不相关进程间交换数据)
1.shell 命令创建命名管道:$ mkfifo /tmp/my_fifo
查看命名管道命令:$ ls –lF /tmp/my_fifo
2. 程序创建命名管道
(1)代码:

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc,char *argv[]){
    
    
int res = mkfifo("/tmp/my_fifo",0777); //创建一个命名管道
if(res==0)   //创建成功则打印输出
printf("FIFO created\n");
exit(EXIT_SUCCESS);   
}

(2)运行结果:
在这里插入图片描述
在这里插入图片描述
3.访问命名管道
(1))消费者
读空 FIFO 文件:$cat < /tmp/my_fifo
(2)生产者
向 FIFO 写数据(必须另外开一个终端执行如下命令)
$ echo “Hello,world” > /tmp/my_fifo

猜你喜欢

转载自blog.csdn.net/m0_55726741/article/details/129240272