Linux基础----管道

1. 管道

当数据从一个进程连接流入到另外一个进程的时候,两个进程之间连接的就是一个管道。通常把一个进程的输出通过管道连接到另外一个进程的输入。
比较简单的管道的用法在刚刚接触linux的时候是会经常使用到的,就是通过管道,来查询对应的输出。在这里插入图片描述
管道的本质也是一个文件,但是它并不占用存储空间,占用的是内存空间,Linux上的管道就是一个内存缓冲区。

1.1 无名管道

无名管道在shell里面最常用的方式就是|。无名管道只能在父子进程中使用,父进程产生子进程之前必须打开一个管道文件,然后fork产生一个一模一样的子进程,子进程中就包含有父进程当中的这个同样的管道。

1.1.1无名管道的特性

  • 没有名字,无法使用open()函数,但是可以使用close()函数进行关闭
  • 只提供半双工的通信方式,父子进程都能访问这个文件,只是不能同时进行读写。
  • 只能用于1对1的通信
  • 使用pipe函数来创建一个无名管道

1.1.2 无名管道的使用

pipe()函数用于创建一个匿名管道,可以用于进程间通信的单向数据传输。

int pipe(int pipefd[2]);

想要进行父子进程之间数据的交互,需要执行的操作有。

  • 父进程调用pipe()函数创建匿名管道,得到两个文件描述符pipefd[0],pipefd[1],执行匿名管道的读取段和写入端。
  • 父进程调用fork函数启动子进程,父子进程同时拥有前面管道的两个文件描述符。
  • 父进程向子进程写入数据,父进程需要关闭读取端,子进程关闭写入端,然后夫进程将数据写入到管道中
  • 子进程向夫进程传递数据,父进程需要关闭写入端,子进程关闭读取端。
  • 不需要管道的时候,在进程中关闭管道即可。

1.2 匿名管道举例

还是例子来得实在:

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>
#include <sys/wait.h>
#include <string.h>
#include <errno.h>

int main(void)
{
	pid_t pid;
	int pipe_fd[2];/*管道的文件描述符*/
	int read_bytes, write_bytes;
	char buf[256];
	const char data[] = "This is a test demo!!!";
	printf("This is fork demo\n");
	
	/*创建管道*/
	if(pipe(pipe_fd) < 0){
		printf("pipe create failed!!!\r\n");
		exit(-1);
	}
	
	/*调用fork函数创建子进程*/
	pid = fork();
	if(pid == -1)
	{
		printf("fork error!!!\r\n");
	}
	
	/*子进程*/
	else if(pid == 0)
	{
		/*子进程关闭写描述符*/
		close(pipe_fd[1]);
		sleep(3);

		/*子进程来获取管道中的内容*/
		if((read_bytes = read(pipe_fd[0],buf,256)) > 0)
		{
			printf("%d bytes from pipe is '%s'\n",read_bytes, buf);
		}

		/*子进程中关闭读取文件描述符*/
		close(pipe_fd[0]);
		exit(0);
	}
	
	/*父进程*/
	else if(pid > 0 ){
		/*父进程关闭读描述符*/
		close(pipe_fd[0]);
		sleep(1);
		if((write_bytes = write(pipe_fd[1], data, strlen(data))) != -1){
			printf("Parent write %d bytes : '%s'\n", write_bytes, data);
		}

		/*关闭父进程写描述符*/
		close(pipe_fd[1]);

		/*收集子进程退出状态*/
		waitpid(pid, NULL, 0);
		exit(0);
	}
}	

上面的代码实现的功能就是父进程像无名管道中写入数据,子进程从无名管道中读出数据。在父进程写入数据的时候,需要先关闭父进程对无名管道的读取,在子进程进行读取数据的时候,需要关闭子进程的写入使能。
在这里插入图片描述

1.3 有名管道

前面的无名管道,只能在父子进程之间进行数据的传输。如果想在两个不同的进程之间进行数据的交互,可以使用FIFO来完成这个工作。作为一个FPGAer,发现FIFO真的到处都是啊,真是个好东西。
在Linux当中可以使用mkfifo来创建一个有名管道。

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

需要传递的参数有:

  • 一个具体的路径,mkfifo会根据这个路径来创建一个fifo文件。
  • 模式: 像文件的权限:
    • O_RDONLY:读管道
    • O_WRONLY: 写管道
    • O_RDWR: 读写管道
    • O_NONBLOCK:非阻塞
    • O_CREAT:该文件不存在就创建一个文件
      返回值为0表示成功,其他表示错误。

1.3.1 FIFO读写过程当中的操作

对FIFO进行写操作

  • 管道是阻塞类型的,且当前FIFO没有数据,那么这个进程将会一直等待,直到FIFO中有数据。
  • 如该管道是非阻塞的,不论FIFO内是否有数据,这个读取的进程都会立即执行读取操作。如果FIFO中 没有数据,该函数将立刻返回0。

对FIFO进行写操作

  • 管道是阻塞类型的,当FIFO被写满之后想要再往里面写入数据,需要等到FIFO中有足够的空间。
  • 若该管道是非阻塞类型并且当前没有足够空间来进行全部数据的写入,则写操作进行部分或者调用失败。

1.4 有名管道的使用

还是用一个例子来记录下这个用法:
有名管道的具体的使用方法是:
第一个进程

  • 进程使用mkfifo创建一个管道
  • 使用open函数,打开这个管道。
  • 调用read write函数来对管道进行操作
  • 调用close来关闭这个管道

第二个进程

  • 使用open函数打开这个管道
  • 进行read,write操作
  • 使用close函数,来关闭这个管道

读取FIFO进程

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

#define MY_FIFO "/tmp/my_fifo"

int main(int argc, char * argv[])
{
    char buf[512];
    int fd;
    int bytes_read;

    if(access(MY_FIFO, F_OK) == -1){
        /*create a fifo*/
        if((mkfifo(MY_FIFO, 0666)<0) && (errno != EEXIST)){
            printf("create fifo failed\n");
            exit(-1);
        }
    }

    /*open fifo, read only*/
    fd = open(MY_FIFO, O_RDONLY);

    if(fd == -1){
        printf("open fifo failed\n");
        exit(-1);
    }

    /*read data from fifo*/
    while (1)
    {
        memset(buf, 0, 512);
        
        if ((bytes_read = read(fd, buf, 512)) > 0)
        {
            printf("read %s  from fifo\r\n", buf);
        }
    }

    /*close the fifo*/
    close(fd);

    exit(0);
}

写入FIFO进程

#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

#define MY_FIFO "/tmp/my_fifo"

int main(int argc, char * argv[]){
    char buf[512];
    int fd;
    int bytes_write;

    fd = open(MY_FIFO, O_WRONLY);
    if (fd == -1)
    {
        printf("open file failed\r\n");
    }
     sscanf(argv[1],"%s",buf);
     
    if ((bytes_write = write(fd, buf, 512)) > 0)
    {
        printf("write %s to fifo\r\n",buf);
    }
    close(fd);

    exit(0);
}

从一个进程发送,另外一个进程接收。
在这里插入图片描述

参考:

i.MX6ULL开发板资料

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: Linux是一种操作系统,而-bash是Linux中的一种shell(命令行解释器),它允许用户在命令行中输入命令并执行它们。-bash是Linux默认的shell之一,它提供了许多有用的功能和命令,使用户能够更轻松地管理和操作系统。 ### 回答2: Linux -bash 是指 Linux 系统中的 Bash(Bourne Again SHell)终端或命令行界面。 Bash 是一种常用的 Unix shell,它是用于管理和执行命令行操作的基础工具。它允许用户在 Linux 系统上输入和执行各种命令,与系统进行交互,并管理文件和文件夹。 Linux -bash 提供了一个交互式环境,用户可以在其中执行各种命令。它可以用于执行系统管理任务,如安装软件包、配置网络设置、管理用户和权限等。此外,还可以使用 bash 脚本编写批量处理任务,实现自动化和脚本化操作。 在 -bash 终端中,用户可以使用各种命令来探索文件系统、浏览文件和文件夹、编辑文本文件等。用户可以通过输入命令和参数,实现不同的操作和功能,比如复制、移动、删除文件,修改文件权限等等。 -bash 终端也提供了强大的命令行编辑和历史纪录功能。用户可以使用上下箭头键浏览之前输入的命令,并进行修改和再次执行。此外,可以使用 Tab 键进行自动完成操作,节省输入命令的时间和工作量。 总而言之,Linux -bash 是 Linux 系统中常用的命令行界面,在系统管理、文件操作和批处理方面提供了丰富的功能和灵活性,是 Linux 用户和系统管理员必不可少的工具之一。 ### 回答3: Linux的-bash是一种命令行解释器,也称为Bourne Again SHell。Bash是Unix操作系统中最常用的shell之一,由于Linux是基于UNIX的,因此Bash也成为了Linux中最常用的shell。 -bash表示当前用户所使用的shell环境是Bash。在Linux系统中,当我们打开终端或者SSH登录到服务器时,会自动进入一个shell环境,这个环境中我们可以使用各种命令来执行各种操作。 Bash是一个功能强大且灵活的shell,它支持大量的命令,可以用于管理和操作文件、目录、进程、权限、网络等各个方面。通过Bash,我们可以输入命令并执行,也可以编写shell脚本来进行自动化操作。 在-bash下,我们可以使用各种命令来管理Linux系统,比如ls命令用于列出当前目录下的文件和子目录,cd命令用于切换目录,pwd命令用于显示当前所在的目录,mkdir命令用于创建新的目录,rm命令用于删除文件和目录,等等。 此外,Bash还支持各种运算和控制结构,允许我们编写复杂的shell脚本来自动化任务。我们可以使用if语句来进行条件判断,使用for和while循环来进行重复操作,还可以通过管道(|)来连接多个命令,实现更复杂的操作。 总之,Linux的-bash是一种强大的命令行解释器,它为我们提供了丰富的命令和功能,使我们能够高效地管理和操作Linux系统。无论是日常使用还是系统管理,熟练掌握-bash都是非常重要的。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值