I/O重定向编程

管道编程

1. I/O重定向

(1) 运用open-close-open方法
//demo1.c
#include <stdio.h>
#include <fcntl.h>

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);
	}

	/* read and print three lines */

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

编译并运行上述代码

$ gcc 0o demo1 demo1.c
$ ./demo1   //实现输入重定向
(2) 利用dup2()函数实现重定向
// demo2.c
#include <unistd.h>
#include <stdio.h>
int main ()
	{
	int fileId;
	fileId = creat( "ls.txt",0640 );
  if( fileId < 0 )  
		{  
		fprintf( stderr, "error creating ls.txt\n" ); 
		exit (1);     
		}
	dup2( fileId, 1 ); //重新定义标准输出
  close( fileId );     		
  execl( "/bin/ls", "ls", 0 );
}

编译并运行上述代码

$ gcc -o demo2 demo2.c //编译并链接
$ ./demo2      //执行demo2
$ ls ls.txt  // 观察ls.txt的内容

2. 管道

(1) 无名管道

利用无名管道实现父子进程之间的通信

//demo3.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(void) {
    pid_t pid;
    int fd_arr[2], i, n;
    char chr;
    pipe(fd_arr);
    pid = fork();
    if (pid == 0)  {   // 子进程
    		close (fd_arr[1]); // 关闭写入端
 		// 从管道中读取数据
       	for( i = 0 ; i < 10 ; i++) {
       		read(fd_arr[0], &chr, 1);
 			printf("%c\n", chr);
 		}
 		close(fd_arr[0]);
 		exit (0);
    }
    // 父进程
    close (fd_arr[0]); // 关闭管道的读入端
    // 向管道中写入数据
    for( i = 0 ; i < 10 ; i++) {
    		chr = 'a' + i;
     		write (fd_arr[1], &chr, 1);
       	sleep(1);
    }
    close (fd_arr[1]);
}

编译并运行上述代码

$ gcc -o demo3 demo3.c 、、编译并链接
$ ./demo3 //执行
(2) 命名管道
  • (a) 创建命名管道
..demo4.c
#include <sys/types.h>
#include <sys/stat.h>
int main(void){
    mkfifo("fifo",0660); //创建命名管道
}

编译并运行上述代码

$ gcc -o demo4 demo4.c //编译并链接
$ ./demo4             //
$ ls -l fifo //显示命名管道文件
  • (b) 想命名管道文件中写入信息
//demo5.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void){
int fd=open("fifo",O_WRONLY); //write to fifo
write(fd,"fifo test\n",10);
}

编译并执行上述代码

$ gcc -o demo5 demo5.c //编译并链接
$ ./demo5  //

$ ./demo5 
  • © 读取命名管道文件
// exam6.c
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void){
char buf[256];
int fd=open("fifo",O_RDONLY); //read from fifo
read(fd,buf,256);
printf("%s",buf);
}

编译并执行上述代码

$ gcc -o demo6 demo6.c
$ ./demo6

3. 思考题

  1. 研究Linux实现重定向的原理

  2. 如何运用管道实现两个进程间的通信