嵌入式Linux并发程序设计,进程间通信方式,有名管道,有名管道特点,有名管道创建mkfifo()

1,有名管道的特点

  1. 对应管道文件,可用于任意进程之间进行通信:有名管道创建好之后,在系统中有实际的文件和有名管道对应,任意两个进程可以通过路径和文件名指定同一个有名管道进行通信
  2. 打开管道时可指定读写方式:有名管道用open()打开的时候可以指定不同的读写方式,从而可以确定读端和写端
  3. 通过文件IO操作,内容存放在内存中:通过文件IO read()和write()进行操作。虽然有名管道有一个实际的文件被创建,在文件系统中可见,但是往管道中写入的所有内容实际上依然是存放在内存中的(跟无名管道一样),当所有的读端和写端都关闭的时候,管道存放在内存中的内容都会被释放
  4. 有名管道打开的时候有可能会阻塞。当只有读端或只有写端的时候,open()会阻塞,只有当读端和写端同时存在的时候,open()才会返回,程序才会继续执行。

2,有名管道的创建mkfifo()

#include <unistd.h>
#include <fcntl.h>
int mkfifo(const char *path, mode_t mode);

  1. 成功时返回0,失败时返回EOF(如果创建的管道已经存在,创建就会失败)
  2. path 创建的管道文件路径
  3. mode 管道文件的权限,如0666(管道文件的权限主要是读写权限)

3,有名管道读写—示例

进程A:循环从键盘输入并写入有名管道myfifo,输入quit时退出
进程B:循环统计进程A每次写入myfifo的字符串的长度

/*  create_fifo.c  */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
	if(mkfifo("myfifo",0666) < 0)
	{
		perror("mkfifo");
		exit(-1);
	}

	return 0;
}
/*  write_fifo.c  */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>

#define N 32
int main(int argc, const char *argv[])
{
	char buf[N];
	int pfd;

	if((pfd = open("myfifo",O_WRONLY)) < 0)
	{
		perror("open");
		exit(-1);
	}
	printf("write myfifo\n");//进程打开管道后显示这一句
	while(1)
	{
		printf("Please input a string (quite exit!\n");
		fgets(buf,N,stdin);
		if(strcmp(buf,"quite\n") == 0)break;
		write(pfd,buf,N);
	}

	close(pfd);

	return 0;
}
/*  read_fifo.c  */
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define N 32

int main(int argc, const char *argv[])
{
	char buf[N];
	int pfd;

	if((pfd = open("myfifo",O_RDONLY)) < 0)
	{
		perror("open");
		exit(-1);
	}
	printf("read myfifo\n");//进程打开管道后显示这一句	
	while(read(pfd,buf,N) > 0)//写端存在,管道中没有数据的时候,读管道阻塞;写端不存在,管道中没有数据的时候,read()返回0
	{
		printf("the length of string is %d\n",strlen(buf));
	}
	close(pfd);

	return 0;
}

1,创建好三个c文件,并编译

linux@linux:~/test/stdio/fifo_sample$ ls
fifo_create.c  fifo_read.c  fifo_write.c
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_create.c -o fifo_create.out
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_write.c -o fifo_write.out
linux@linux:~/test/stdio/fifo_sample$ gcc fifo_read.c -o fifo_read.out
linux@linux:~/test/stdio/fifo_sample$ ls
fifo_create.c  fifo_create.out  fifo_read.c  fifo_read.out  fifo_write.c fifo_write.out

2,运行fifo_create.out,可以看到多了管道文件

linux@linux:~/test/stdio/fifo_sample$ ./fifo_create.out 
linux@linux:~/test/stdio/fifo_sample$ ll
total 44
drwxrwxr-x 2 linux linux 4096 11月 12 11:13 ./
drwxrwxr-x 6 linux linux 4096 11月 12 01:01 ../
-rw-rw-r-- 1 linux linux  185 11月 12 10:13 fifo_create.c
-rwxrwxr-x 1 linux linux 7418 11月 12 11:04 fifo_create.out*
-rw-rw-r-- 1 linux linux  379 11月 12 11:03 fifo_read.c
-rwxrwxr-x 1 linux linux 7647 11月 12 11:05 fifo_read.out*
-rw-rw-r-- 1 linux linux  438 11月 12 11:03 fifo_write.c
-rwxrwxr-x 1 linux linux 7681 11月 12 11:04 fifo_write.out*
prw-rw-r-- 1 linux linux    0 11月 12 11:13 myfifo|
  • 可以看到管道文件大小是0,实际上管道文件大小永远是0,因为管道中的内容是保存在内存里的,而不是磁盘上

3,运行fifo_read.out或fifo_write.out,可以看到程序处于阻塞状态。以先运行fifo_read.out为例(先运行写管道也一样)

linux@linux:~/test/stdio/fifo_sample$ ./fifo_read.out 

linux@linux:~/test/stdio/fifo_sample$ ps -aux |grep fifo
linux     3089  0.0  0.5  15196  6072 pts/10   S+   10:49   0:01 vi fifo_read.c
linux     3306  0.0  0.0   2024   280 pts/12   S+   11:15   0:00 ./fifo_read.out
linux     3314  0.0  0.0   6108   852 pts/0    S+   11:18   0:00 grep --color=auto fifo
  1. 当进程打开一个有名管道的时候,如果当前只有读端或只有写端,open()会阻塞
    open()的下一条指令
    printf(“read myfifo\n”);//进程打开管道后显示这一句
    没有执行
  2. 只有当读端和写端都存在是,两个进程中的open()才能正常执行

4,在另一个终端运行

读进程 写进程
linux@linux:~/test/stdio/fifo_sample$ ./fifo_read.out
write myfifo
linux@linux:~/test/stdio/fifo_sample$ ./fifo_write.out
write myfifo
Please input a string (quite exit!
the length of string is 4
qwe
Please input a string (quite exit!
the length of string is 2
w
Please input a string (quite exit!
linux@linux:~/test/stdio/fifo_sample$
quite
linux@linux:~/test/stdio/fifo_sample$
  1. 运行fifo_write.out后,管道有了写端,读进程和写进程的open()才能正常运行,可以看到open()的下一条指令
    printf(“read myfifo\n”);//进程打开管道后显示这一句
    printf(“write myfifo\n”);//进程打开管道后显示这一句
    正常执行了
  2. 当写端输入quite时,写端不存在了,当写端不存在了,并且管道中没有数据数据,读管道会立刻返回0,返回0,就会退出循环,程序结束

猜你喜欢

转载自blog.csdn.net/m0_37542524/article/details/83990383