Linux系统编程 87 文件用于进程间通信

本文介绍了一个简单的进程间通信示例,使用文件作为共享媒介。通过父子进程及无血缘关系进程间的文件操作,展示了文件在进程间通信中的作用。

学习笔记

文件完成进程间通信
下面代码不需要你会写

$cat fileforprocesscommuncation.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<fcntl.h>//O_RDWR
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int main(int argc, char *argv[])
{
    int fd1 ,fd2;
    pid_t pid;
    char buf[1024];
    char *str ="--------test for shared fd in parent and child process--------\n";

    pid = fork();
    if(pid < 0)
    {
        sys_err("fork error!");
    }
    else if(0 == pid)
    {
        fd1 = open("test.txt",O_RDWR);
        if( fd1 < 0)
        {
            sys_err("open error!");
        }
        
        write(fd1, str,strlen(str));
        printf("child wrote over....\n");
    }
    else
    {
        fd2 = open("test.txt",O_RDWR);
        if(fd2 < 0)
        {
            sys_err("open error!");
        }

        sleep(1);
    
        int len = read(fd2,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,len);

        wait(NULL);
    }


}
$make fileforprocesscommuncation
gcc  fileforprocesscommuncation.c -o fileforprocesscommuncation -Wall -g
$./fileforprocesscommuncation 
open error!: No such file or directory
$open error!: No such file or directory

$touch test.txt
$./fileforprocesscommuncation 
child wrote over....
--------test for shared fd in parent and child process--------


读管道会阻塞,普通文件会么?
实际上除了管道 设备文件 网络文件 有阻塞
普通文件是没有的。
注意阻塞是文件的特性 而不是read函数的特性。


修改代码如下:

$cat fileforprocesscommuncation.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<fcntl.h>//O_RDWR
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int main(int argc, char *argv[])
{
    int fd1 ,fd2;
    pid_t pid;
    char buf[1024];
    char *str ="--------test for shared fd in parent and child process--------\n";

    pid = fork();
    if(pid < 0)
    {
        sys_err("fork error!");
    }
    else if(0 == pid)
    {
        fd1 = open("test.txt",O_RDWR);
        if( fd1 < 0)
        {
            sys_err("open error!");
        }
        sleep(3);        
        write(fd1, str,strlen(str));
        printf("child wrote over....\n");
    }
    else
    {
        fd2 = open("test.txt",O_RDWR);
        if(fd2 < 0)
        {
            sys_err("open error!");
        }

        //sleep(1);
    
        int len = read(fd2,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,len);

        wait(NULL);
    }


}
$make fileforprocesscommuncation
gcc  fileforprocesscommuncation.c -o fileforprocesscommuncation -Wall -g
$./fileforprocesscommuncation 
--------test for shared fd in parent and child process--------
child wrote over....


为什么出现和上面普通文件不存在阻塞现象?

test.txt 文件已经有内容了

$cat test.txt
--------test for shared fd in parent and child process--------
$rm test.txt 
$touch test.txt
$./fileforprocesscommuncation 
child wrote over....
$cat fileforprocesscommuncation.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>
#include<sys/wait.h>
#include<fcntl.h>//O_RDWR
void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int main(int argc, char *argv[])
{
    int fd1 ,fd2;
    pid_t pid;
    char buf[1024];
    char *str ="--------test for shared fd in parent and child process--------\n";

    pid = fork();
    if(pid < 0)
    {
        sys_err("fork error!");
    }
    else if(0 == pid)
    {
        fd1 = open("test.txt",O_RDWR);
        printf(" fd1 is %d\n",fd1);
        if( fd1 < 0)
        {
            sys_err("open error!");
        }
        sleep(3);        
        write(fd1, str,strlen(str));
        printf("child wrote over....\n");
    }
    else
    {
        pid_t fd3 = open("test1.txt",O_RDWR);
        printf("fd3 is %d\n",fd3);

        fd2 = open("test.txt",O_RDWR);
        printf("fd2 is %d\n",fd2);
        if(fd2 < 0)
        {
            sys_err("open error!");
        }

        //sleep(1);
    
        int len = read(fd2,buf,sizeof(buf));
        write(STDOUT_FILENO,buf,len);

        wait(NULL);
    }


}
$touch test.txt
$ll
total 40
drwxrwxr-x 2 ubuntu ubuntu  4096 1月  17 22:19 ./
drwxrwxr-x 9 ubuntu ubuntu  4096 1月  17 21:32 ../
-rwxrwxr-x 1 ubuntu ubuntu 20512 1月  17 22:18 fileforprocesscommuncation*
-rw-rw-r-- 1 ubuntu ubuntu   949 1月  17 22:18 fileforprocesscommuncation.c
-rw-rw-r-- 1 ubuntu ubuntu   169 1月  17 21:33 makefile
-rw-rw-r-- 1 ubuntu ubuntu     0 1月  17 22:18 test1.txt
-rw-rw-r-- 1 ubuntu ubuntu     0 1月  17 22:19 test.txt
$./fileforprocesscommuncation 
fd3 is 3
fd2 is 4
 fd1 is 3
child wrote over....


可以看出就是父子进程打开同一个文件
文件描述符也不一定一样。


其实没有血缘关系的进程,也是可以通过文件来通信
因为打开打开的文件在内存的缓冲区是同一块的。


这里面要注意和父子进程共享文件描述符的概念区分开来。
因为这个程序打开文件是在各自的进程中打开的。

下面是两个无血缘关系的进程通过文件来实现通信的例子

vsp 打开两个终端分屏之后又
在末行模式下
:set mouse=a

然后鼠标就可以两个分屏之间自由切换。

set mouse=a后,vim中右键无法复制了,重启终端后可以

$cat test1.c
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<string.h>
#include<stdio.h>
int main()
{
    char buf[1024];
    char *str = "--------test1 success------\n";
    int ret;

    int fd = open("test.txt",O_RDWR|O_TRUNC|O_CREAT,0664);

    write(fd,str,strlen(str));
    printf("test1 write into test.txt finish\n");

    sleep(15);

    lseek(fd,0,SEEK_SET);
    ret = read(fd,buf,sizeof(buf));
    ret = write(STDOUT_FILENO,buf,ret);

    if(-1 == ret)
    {
        perror("write second error!");
        exit(1);
    }
    close(fd);
    return 0;
}
$cat test2.c 
#include<unistd.h>
#include<stdlib.h>
#include<fcntl.h>
#include<string.h>
#include<stdio.h>
int main()
{
    char buf[1024];
    char *str = "test2 write success-----\n";
    int ret;

    sleep(2);
    int fd = open("test.txt",O_RDWR);
    ret =read(fd,buf,sizeof(buf));

    write(STDOUT_FILENO,buf,ret);
    write(fd,str,strlen(str));

    printf("test2 read/write finish\n");

    close(fd);
    return 0;
}


打开一个终端:
实行test1

$./test1
test1 write into test.txt finish
--------test1 success------
test2 write success-----

打开另外一个终端2
实行test2

$./test2
--------test1 success------
test2 read/write finish


 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值