Linux学习笔记(13)-进程通信|命名管道

  匿名管道只能在具有亲属关系的进程间通信,那么如果想要在不具有亲戚关系,想在陌生人之间通信,那又该怎么办呢?

  别慌,Linux身为世界上*强大的操作系统,当然提供了这种机制,那便是命名管道……

  所谓命名管道,那便是拥有名字的管道,同时也被称之为FIFO,谈到FIFO,那么做过单片机开发的同学想必是不陌生的。

  在很多单片机的项目中,都使用过FIFO,FIFO其实是一种队列,先进先出,这样可以保证读出数据和写入数据的一致性。

  使用FIFO文件,便可以在不同的,且不具有亲属关系的进程中进程通信。

  创建命名管道的函数叫mkfifo(),关联两个头文件,分别是sys/types.hsys/stat.h

  函数mkfifo的原形如下:

  int mkfifo(const char * pathname, mode_t mode);

  其中参数pathname是,创建的文件名,在这里可以理解为管道名,

  参数mode是,指定所创建的文件的操作权限。

  在mkfifo创建管道之后,需要通过命名管道通信的进程,需要打开该管道文件,然后通过read,write等函数,像操作普通文件一样进行通信。

  现在开始编写代码:

  在两个没有亲戚关系的进程间通信,甲进程向乙进程发送信号,乙进程回复。

  下面是主机端的代码!

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<errno.h>
int main(int argc, char * argv[])
{
    const char * fifoname = "fifo_temp";
    int fd;
    int byte;
    int ret;
    int datafd;
    char buffer[] = {"nihao!"};

    if (access(fifoname,F_OK) < 0)//这个函数的说明在最后!
    {
        ret =mkfifo(fifoname,0777);
        if (ret < 0)
        {
            printf("主机端命名管道创建失败!\n");
            exit(0);
        }
    }
    printf("主机端打开FIFO文件……\n");
    fd = open(fifoname,O_WRONLY);//不能以O_RDWR模式打开FIFO文件进行读写操作
    printf("errno = %d\n",errno);
    if (fd > 0)
    {
        printf("主机端打开FIFO成功!\n");
        printf("主机端开始发送数据!\n");
        ret = write(fd,buffer,sizeof(buffer));
        if (ret < 0)
        {
            printf("主机端写入FIFO文件失败!\n");
            exit(0);
        }
        printf("主机端文件写入FIFO成功!\n");
        close(fd);
    }
    else
    {
        printf("主机端打开FIFO文件失败!\n");
    }

    return 0;
}

 下面是从机端的代码!

#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>

int main(int argc, char *argv[] )
{
    const char *fifoname = "fifo_temp";
    int fd,datafd,ret;
    int byte;

    char buffer[1024];

    fd = open(fifoname, O_RDONLY);
    printf("从机端打开FIFO文件!\n");
    if (fd > 0)
    {
        printf("从机端打开FIFO文件成功!\n");
        byte = read(fd,buffer,1024);
        printf("从机端收到文件为:%s.\n",buffer);
        close(fd);
    }

    return 0;
}

编译完毕后,结果如下:

黄色的那个就是管道文件,看它的开头是用P表示的。

程序执行结果如下:

  稍微解说一下,首先执行主机端,对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY)。

  open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止由于管道的操作open是阻塞的,所以主机端将会在

  fd = open(fifoname,O_WRONLY); 这条代码中等待,只有在从机端启动后,以只读方式,同样也打开了那条管道,主机端才会继续执行下去。  如果不想阻塞,那么需要在open函数的调用的第二个参数中,设置选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞, 加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。————————————————————————————————————————————————————————————————————————————————————————————————————————————

  这里为什么要加个与符号&呢?是为了让程序在后台执行,这样我们才能在主机端运行过程中,启动从机端的程序。

  当然,你也可以将主机端的程序设为守护进程,这样也能达到同样的效果。

————————————————————————————————————————————————————————————————————————————————————————————————————————————
 知识小结:在主机端中,我使用了一个名叫access的函数。

 access():判断是否具有存取文件的权限

表头文件
    #include<unistd.h>
定义函数
    int access(const char * pathname, int mode);
函数说明
    access()会检查是否可以读/写某一已存在的文件。参数mode有几种情况组合, R_OK,W_OK,X_OK 和F_OK。R_OK,W_OK与X_OK用来检查文件是否具有读取、写入和执行的权限。

  F_OK则是用来判断该文件是否存在。由于access()只作权限的核查,并不理会文件形态或文件内容,因此,如果一目录表示为“可写入”,表示可以在该目录中建立新文件等操作,而非意味此目录可以被当做文件处理。例如,你会发现DOS的文件都具有“可执行”权限,但用execve()执行时则会失败。
返回值
    若所有欲查核的权限都通过了检查则返回0值,表示成功,只要有一权限被禁止则返回-1。

时间: 2024-12-25 22:20:53

Linux学习笔记(13)-进程通信|命名管道的相关文章

Linux学习笔记033_11进程

ps:(process information,静态的) 显示进程信息,不加参数显示当前终端的进程 a:包括所有终端的进程 x:不属于任何终端的进程,和任何用户无关系的进程 u:显示出进程的拥有人 f:显示进程的附属关系(依赖关系,父子进程) USER:进程的拥有人 PID:进程ID,默认用进程ID排序 VSZ:程序在运行时调用多少虚拟内存 RSS:真实内存 TTY:?不属于任何终端,进入终端之前就运行 STAT:状态,s为睡眠 TIME:进程持续时间 COMMAND:运行这个进程的指令 ps

Linux学习笔记(12)-进程间通信|管道

Linux的进程间通信有几种方式,包括,管道,信号,信号灯,共享内存,消息队列和套接字等-- 现在一个个的开始学习! -------------------------------------------------- 管道是一个进程链接另一个进程的数据通道,它通常是把一个进程的输出,接到另一个进程的输入,从而传递数据. 在Linux的终端上,用单竖线|来表示,那么,这个符号可以做什么呢? 举个栗子,如果我用ps -ef命令,可以查看我当前所有的进程: 正如上图表示,显示出来的东西太多了,让人眼

linux学习笔记之进程管理

ps    process state unix    system V BSD ps -e    显示所有进程(tty相关的是前台进程 ?tty无关) -u    用户相关 -f    full    format    listing -F    print extra    information -o command  选择显示字段 ps aux ps -ef ps -eF bsd风格 a x state: S    sleep s    session loader <    high

C# 进程通信-命名管道

之前看wcf服务的时候看到wcf有支持管道通信协议,之前不知道,最近刚好有用到这个,这里写个简单实例 .net有已经封装好的pip通信的对象NamedPipeServerStream 和NamedPipeClientStream对象,底层应该还是调用C++实现的api实现的 对服务端和客户端做个简单的封装方便调用: server: public class PipServer:Log { public Action<string> ReceiveEvent; NamedPipeServerSt

Linux学习笔记:进程管理

显示系统所有进程:ps aux: 重置某个进程:kill -HUP /var/run/crond.pid: 六亲不认杀死进程:cat /var/run/crond.pid | xargs kill -9: ps aux|grep -v grep |grep ssh|awk '{print $2}'1870 ps aux|grep -v grep |grep ssh|awk '{print $2}' |xargs -L 1 sudo kill -HUP #sudo 提升权限# ps -aux 提示

Linux学习笔记13——sed基本用法

三大基本文本处理工具:grep,sed(流编辑器),awk sed: Stream EDitor 行编辑器:sed全屏编辑器:vi sed: 模式空间默认不编辑文件本身,仅对模式空间中的数据做处理:而后,处理结束后,将模式空间打印至屏幕: sed [options] 'AddressCommand' file ...(对这些文件中的符合这个地址address指定范围内的行,执行以下命令编辑)-n: 静默模式,不再默认显示模式空间中的内容-i: 直接修改原文件(这个要注意!!!!!!)-e SCR

进程通信——命名管道通信

private static void WaitData() { using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.InOut, 1)) { try { pipeServer.WaitForConnection(); pipeServer.ReadMode = PipeTransmissionMode.Byte; using (StreamReade

Linux System Programming 学习笔记(五) 进程管理

1. 进程是unix系统中两个最重要的基础抽象之一(另一个是文件) A process is a running program A thread is the unit of activity inside of a process the virtualization of memory is associated with the process, the threads all share the same memory address space 2. pid The idle pro

Linux学习笔记(5)-进程管理

进程简介 进程是正在执行的一个程序或命令,每一个进程都有自己的地址空间,并占有一定的系统资源.感性的认识,进程就是一个正在运行的程序 进程管理的作用 判断服务器的运行状态 查看系统中有哪些进程 杀死进程(很少用,一般会采用正常的关闭手段) 查看系统所有的进程 #ps aux #ps -le 输出信息各字段的含义 USER:进程是由哪个用户产生的 PID:进程的ID号 %CPU:进程占用CPU资源的百分比 %MEM:进程占用物理内存的百分比 VSZ:该进程占用虚拟内存的大小,单位KB RSS:该进