首页 > 系统相关 >进程间通信-信号-pipe-fifo

进程间通信-信号-pipe-fifo

时间:2022-11-13 16:35:26浏览次数:42  
标签:pipe int fifo 间通信 fd printf line include

fifo管道

在有名管道(named pipe或FIFO)提出后,管道(pipe)限制得到了克服。

  • FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信。因此,通过FIFO不相关的进程也能交换数据。
  • FIFO类似于放在草坪上的一根塑料水管,任何人都可以将此水管的一段放在耳边,而另一个人通过水管向对方说话。而当没有人使用的时候,水管仍然存在。FIFO可以看做由文件名标志的一根水管。
  • 值得注意的是,FIFO严格遵循先进先出(first in first out),对管道及FIFO的读总是从开始处返回数据,对它们的写则把数据添加到末尾。
    它们不支持诸如lseek()等文件定位操作。

管道常用于两个方面:

  • (1)在shell中时常会用到管道(作为输入输入的重定向),在这种应用方式下,管道的创建对于用户来说是透明的;
  • (2)用于具有亲缘关系的进程间通信,用户自己创建管道,并完成读写操作。

FIFO可以说是管道的推广,克服了管道无名字的限制,使得无亲缘关系的进程同样可以采用先进先出的通信机制进行通信:(1)提供一个路径名与之关联;(2)严格遵循先进先出(first in first out) 。

管道和FIFO的数据是字节流,应用程序之间必须事先确定特定的传输"协议",采用传播具有特定意义的消息。

要灵活应用管道及FIFO,理解它们的读写规则是关键。

一、代码

1.testmf.c

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

int main()
{
	int res = mkfifo("/tmp/myfifo", 0777);
	if (res == 0) {
		printf("FIFO created \n");
	}
	exit(EXIT_SUCCESS);
}

以“0777”文件创建模式(即-rwx rwx rwx)创建管道。

  • 777 代表
    该文件拥有者对该文件拥有读写操作的权限
    该文件拥有者所在组的其他成员对该文件拥有读写操作的权限
    其他用户组的成员对该文件也拥有读写操作权限

  • 666代表
    该文件拥有者对该文件拥有读写的权限但是没有操作的权限
    该文件拥有者所在组的其他成员对该文件拥有读写的权限但是没有操作的权限
    其他用户组的成员对该文件也拥有读写权限但是没有操作的权限

2.consumer.c

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

#define FIFO_NAME "/tmp/myfifo"
#define BUFFER_SIZE PIPE_BUF


int main()
{
	int pipe_fd;
	int res;

	int open_mode = O_RDONLY;
	char buffer[BUFFER_SIZE + 1];
	int bytes = 0;

	memset(buffer, 0, sizeof(buffer));

	printf("Process %d opeining FIFO O_RDONLY \n", getpid());
	pipe_fd = open(FIFO_NAME, open_mode);
	printf("Process %d result %d\n", getpid(), pipe_fd);

	if (pipe_fd != -1) {
		do {
			res = read(pipe_fd, buffer, BUFFER_SIZE);
			bytes += res;
		} while (res > 0);
		close(pipe_fd);
	} else {
		exit(EXIT_FAILURE);
	}

	printf("Process %d finished, %d bytes read\n", getpid(), bytes);
	exit(EXIT_SUCCESS);
}

3.producer.c

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

#define FIFO_NAME "/tmp/myfifo"
#define BUFFER_SIZE PIPE_BUF
#define TEN_MEG (1024 * 1024 * 10)

int main()
{
	int pipe_fd;
	int res;
	int open_mode = O_WRONLY;

	int bytes = 0;
	char buffer[BUFFER_SIZE + 1];

	if (access(FIFO_NAME, F_OK) == -1) {
		res = mkfifo(FIFO_NAME, 0777);
		if (res != 0) {
			fprintf(stderr, "Could not create fifo %s \n",
				FIFO_NAME);
			exit(EXIT_FAILURE);
		}
	}

	printf("Process %d opening FIFO O_WRONLY\n", getpid());
	pipe_fd = open(FIFO_NAME, open_mode);
	printf("Process %d result %d\n", getpid(), pipe_fd);

	if (pipe_fd != -1) {
		while (bytes < TEN_MEG) {
			res = write(pipe_fd, buffer, BUFFER_SIZE);
			if (res == -1) {
				fprintf(stderr, "Write error on pipe\n");
				exit(EXIT_FAILURE);
			}
			bytes += res;
		}
		close(pipe_fd);
	} else {
		exit(EXIT_FAILURE);
	}

	printf("Process %d finish\n", getpid());
	exit(EXIT_SUCCESS);
}

实现

image
image
image
image

管道pipe

1.listargs.c

#include<stdio.h>

main( int ac, char *av[] )
{
	int	i;

	printf("Number of args: %d, Args are:\n", ac);
	for(i=0;i<ac;i++)
		printf("args[%d] %s\n", i, av[i]);

	fprintf(stderr,"This message is sent to stderr.\n");
}

image

2.pipe.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

#define	oops(m,x)	{ perror(m); exit(x); }

int main(int ac, char **av)
{
	int	thepipe[2],
		newfd,
		pid;

	if ( ac != 3 ){
		fprintf(stderr, "usage: pipe cmd1 cmd2\n");
		exit(1);
	}
	if ( pipe( thepipe ) == -1 )
		oops("Cannot get a pipe", 1);

	if ( (pid = fork()) == -1 )
		oops("Cannot fork", 2);

	if ( pid > 0 ){
		close(thepipe[1]);

		if ( dup2(thepipe[0], 0) == -1 )
			oops("could not redirect stdin",3);

		close(thepipe[0]);
		execlp( av[2], av[2], NULL);
		oops(av[2], 4);
	}

	close(thepipe[0]);

	if ( dup2(thepipe[1], 1) == -1 )
		oops("could not redirect stdout", 4);

	close(thepipe[1]);
	execlp( av[1], av[1], NULL);
	oops(av[1], 5);
}

image

3.pipedemo.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>

int main()
{
	int	len, i, apipe[2];
	char	buf[BUFSIZ];

	if ( pipe ( apipe ) == -1 ){
		perror("could not make pipe");
		exit(1);
	}
	printf("Got a pipe! It is file descriptors: { %d %d }\n",
							apipe[0], apipe[1]);


	while ( fgets(buf, BUFSIZ, stdin) ){
		len = strlen( buf );
		if (  write( apipe[1], buf, len) != len ){
			perror("writing to pipe");
			break;
		}
		for ( i = 0 ; i<len ; i++ )
			buf[i] = 'X' ;
		len = read( apipe[0], buf, BUFSIZ ) ;
		if ( len == -1 ){
			perror("reading from pipe");
			break;
		}
		if ( write( 1 , buf, len ) != len ){
			perror("writing to stdout");
			break;
		}
	}
}

image

4.pipedemo2.c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>


#define	CHILD_MESS	"I want a cookie\n"
#define	PAR_MESS	"testing..\n"
#define	oops(m,x)	{ perror(m); exit(x); }

main()
{
	int	pipefd[2];
	int	len;
	char	buf[BUFSIZ];
	int	read_len;

	if ( pipe( pipefd ) == -1 )
		oops("cannot get a pipe", 1);

	switch( fork() ){
		case -1:
			oops("cannot fork", 2);

		case 0:
			len = strlen(CHILD_MESS);
			while ( 1 ){
				if (write( pipefd[1], CHILD_MESS, len) != len )
					oops("write", 3);
				sleep(5);
			}

		default:
			len = strlen( PAR_MESS );
			while ( 1 ){
				if ( write( pipefd[1], PAR_MESS, len)!=len )
					oops("write", 4);
				sleep(1);
				read_len = read( pipefd[0], buf, BUFSIZ );
				if ( read_len <= 0 )
					break;
				write( 1 , buf, read_len );
			}
	}
}

image

5.stdinredir1.c

#include<stdio.h>
#include<fcntl.h>

int main()
{
	int	fd ;
	char	line[100];

	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );

	close(0);
	fd = open("/etc/passwd", O_RDONLY);
	if ( fd != 0 ){
		fprintf(stderr,"Could not open data as fd 0\n");
		exit(1);
	}

	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
}

image

6.stdinredir2.c

#include<stdio.h>
#include<stdlib.h>
#include<fcntl.h>

//#define	CLOSE_DUP
//#define	USE_DUP2

main()
{
	int	fd ;
	int	newfd;
	char	line[100];

	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );

	fd = open("data", O_RDONLY);
#ifdef CLOSE_DUP
	close(0);
	newfd = dup(fd);
#else
	newfd = dup2(fd,0);
#endif
	if ( newfd != 0 ){
		fprintf(stderr,"Could not duplicate fd to 0\n");
		exit(1);
	}
	close(fd);

	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
	fgets( line, 100, stdin ); printf("%s", line );
}

image

7.testtty.c

#include <unistd.h>

int main()
{
	char *buf = "abcde\n";
	write(0, buf, 6);
}

image

8.whotofile.c

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
	int	pid ;
	int	fd;

	printf("About to run who into a file\n");

	if( (pid = fork() ) == -1 ){
		perror("fork"); exit(1);
	}
	if ( pid == 0 ){
		close(1);				/* close, */
		fd = creat( "userlist", 0644 );		/* then open */
		execlp( "who", "who", NULL );		/* and run	*/
		perror("execlp");
		exit(1);
	}
	if ( pid != 0 ){
		wait(NULL);
		printf("Done running who.  results in userlist\n");
	}

	return 0;
}

image

三、SIGNAL

1.sigactdemo.c

#include<stdio.h>
#include<unistd.h>
#include<signal.h>
#define	INPUTLEN	100
void inthandler();
int main()
{
	struct sigaction newhandler;
	sigset_t blocked;
	char x[INPUTLEN];
	newhandler.sa_handler = inthandler;
	newhandler.sa_flags = SA_RESTART|SA_NODEFER
		|SA_RESETHAND;
	sigemptyset(&blocked);
	sigaddset(&blocked, SIGQUIT);
	newhandler.sa_mask = blocked;
	if (sigaction(SIGINT, &newhandler, NULL) == -1)
		perror("sigaction");
	else
		while (1) {
			fgets(x, INPUTLEN, stdin);
			printf("input: %s", x);
		}
	return 0;
}
void inthandler(int s)
{
	printf("Called with signal %d\n", s);
	sleep(s * 4);
	printf("done handling signal %d\n", s);
}

image

输入信号(其所对应的数据为 s),打印Called with signal s,等待 4* s 秒,打印done handling signal s。

2.sigactdemo2.c

#include <unistd.h>
#include <signal.h>
#include <stdio.h>

void sig_alrm( int signo )
{
	/*do nothing*/
}

unsigned int mysleep(unsigned int nsecs)
{
	struct sigaction newact, oldact;
	unsigned int unslept;

	newact.sa_handler = sig_alrm;
	sigemptyset( &newact.sa_mask );
	newact.sa_flags = 0;
	sigaction( SIGALRM, &newact, &oldact );

	alarm( nsecs );
	pause();

	unslept = alarm ( 0 );
	sigaction( SIGALRM, &oldact, NULL );

	return unslept;
}

int main( void )
{
	while( 1 )
	{
		mysleep( 2 );
		printf( "Two seconds passed\n" );
	}

	return 0;
}

image
每隔2秒打印Two seconds passed。

3.sigdemo1.c

#include<stdio.h>
#include<signal.h>
void	f(int);
int main()
{
	int	i;
	signal( SIGINT, f );
	for(i=0; i<5; i++ ){
		printf("hello\n");
		sleep(2);
	}

	return 0;
}

void f(int signum)
{
	printf("OUCH!\n");
}

image
重复间隔2秒打印5次 hello,若输入 ^C,打印 OUCH!

4.sigdemo2.c

#include<stdio.h>
#include<signal.h>

main()
{
	signal( SIGINT, SIG_IGN );

	printf("you can't stop me!\n");
	while( 1 )
	{
		sleep(1);
		printf("haha\n");
	}
}

image

不断间隔1秒打印 haha,且输入 ^C 无法退出。

5.sigdemo3.c

#include<stdio.h>
#include<string.h>
#include<signal.h>
#include<unistd.h>

#define	INPUTLEN	100

int main(int argc, char *argv[])
{
	void inthandler(int);
	void quithandler(int);
	char input[INPUTLEN];
	int nchars;

	signal(SIGINT, inthandler);//^C
	signal(SIGQUIT, quithandler);//^\

	do {
		printf("\nType a message\n");
		nchars = read(0, input, (INPUTLEN - 1));
		if (nchars == -1)
			perror("read returned an error");
		else {
			input[nchars] = '\0';
			printf("You typed: %s", input);
		}
	}
	while (strncmp(input, "quit", 4) != 0);
	return 0;
}

void inthandler(int s)
{
	printf(" Received signal %d .. waiting\n", s);
	sleep(2);
	printf("  Leaving inthandler \n");
}

void quithandler(int s)
{
	printf(" Received signal %d .. waiting\n", s);
	sleep(3);
	printf("  Leaving quithandler \n");
}

image

当输入正常数据时,将其打印出;
当输入 ^C 时,打印 Received signal 2 .. waiting ,等待2秒后打印Leaving inthandler;
当输入 ^\ 时,打印 Received signal 3 .. waiting ,等待3秒后打印Leaving quithandler。

标签:pipe,int,fifo,间通信,fd,printf,line,include
From: https://www.cnblogs.com/1395372955jth/p/16886210.html

相关文章

  • 20201317 LYX Linux进程间通信学习
    Linux进程间通信1、匿名管道:pipe2、命名管道:fifo3、内存映射:mmap4、信号进程是程序运行资源分配的最小单位。每个进程各自有不同的用户地址空间,任何一个进程的全局变......
  • 流式数据库PipelineDB之BF杂谈
    流式数据库PipelineDB1.导语PipelineDB是一个PostgreSQL的一个流式数据库,是pg社区的一个扩展。下面来引入PipelineDB里面的一些概念:1.1什么是流?流是一种允许客户端将时序......
  • 进程间通信的方式
    进程通信的介绍进程间通信(ProcessToProcessCommunication)是指在并行计算过程中,各进程之间进行数据交互或消息传递,其通信量的大小主要取决于并行设计的粒度划分和各个......
  • 进程间通信-信号-pipe-fifo
    编译运行附件中的代码,提交运行结果截图理解代码,特别是相关系统调用的使用。一、有名管道FIFOFIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文......
  • 进程间通信-信号-pipe-fifo
    1.PIPE1.pipe.c:调用参数所对应的命令2.pipedemo.c:创建一个pipe并读/写3.pipedemo2.c4.stdinredir1.c:打印root权限5.stdinredir2.c6.testtty.c7.whotofile.c......
  • 进程间通信-信号-pipe-fifo
    一、有名管道FIFO(一)知识点1.在有名管道(namedpipe或FIFO)提出后,管道(pipe)限制得到了克服。值得注意的是,FIFO严格遵循先进先出(firstinfirstout),对管道及FIFO的读总是从......
  • 【转】BigPipe学习研究
    1.技术背景FaceBook页面加载技术试想这样一个场景,一个经常访问的网站,每次打开它的页面都要要花费6秒;同时另外一个网站提供了相似的服务,但响应时间只需3秒,那么你会如何选......
  • 进程间通信-信号-pipe-fifo
    一、实验截图(一)fifo(二)pipe(三)signal二、实验代码fifo//consumer#include<stdio.h>#include<stdlib.h>#include<string.h>#include<fcntl.h>#......
  • 进程间通信-信号-pipe-fifo
    进程间通信-信号-pipe-fifo一、信号signal代码1.sigactdemo.c#include<stdio.h>#include<unistd.h>#include<signal.h>#define INPUTLEN 100voidinthandler();int......
  • 进程间通信-信号-pipe-fifo
    一、FIFO有名管道(一)知识点归纳FIFO也称为有名管道,FIFO不同于管道之处在于它提供一个路径名与之关联。有名管道也被称为FIFO文件,是一种特殊的文件。由于linux所有的事物......