博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux学习笔记(13)-进程通信|命名管道
阅读量:4503 次
发布时间:2019-06-08

本文共 3041 字,大约阅读时间需要 10 分钟。

 

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

  别慌,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
#include
#include
#include
#include
#include
#include
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
#include
#include
#include
#include
#include
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。

 

转载于:https://www.cnblogs.com/han-bing/p/6095859.html

你可能感兴趣的文章
Redis的LRU算法
查看>>
高精度算法
查看>>
ABP WebApi 加载错误
查看>>
iTerm的安装以及配置Oh My Zsh
查看>>
windows上的alfred
查看>>
uc/os 上下文切换
查看>>
COJ 2108 Day7-例1
查看>>
自定义 DateTime 格式字符串
查看>>
如何利用报表工具FineReport实现报表列的动态展示
查看>>
ASP.NET基础学习(暴力破解密码)
查看>>
实验11——指针的基础应用
查看>>
FastCGI模块(FastCGI)
查看>>
v-for遍历出的元素上添加click事件,获取对应元素上的属性id值
查看>>
配置打开IE浏览器
查看>>
SVN A C D M G U R I 的含义
查看>>
ZooKeeper--大数据系统的僚机
查看>>
css3新属性object-fit,对页面img处理
查看>>
设计模式--工厂模式Factory
查看>>
五年修炼SEO、一年五万,多嘛?(看时间如何管理?五点论……)
查看>>
Mesos源码分析(16): mesos-docker-executor的运行
查看>>