循序渐进学unix——上机记录(三)
连考了两周试,好久不见……
这次上机主题是“pipe”,内容比较多,我分两次记录。
- 简单的重定向
使用fork创建一个子进程,并把它的标准输出重定向到一个名为sortie的文件。需要掌握的命令/函数有open,close,dup,dup2。
在unix中,一切皆文件。当我们用open函数打开一个普通文件时,函数会返回一个fd(file descriptor)作为这个文件的标识。同样,系统的其他一些设备也被当作文件,从而有各自的标识符。比如0默认表示标准输入,即键盘。这时键盘被当作一个只读的文件。1表示标准输出,2表示标准错误输出,这两个标识符都默认指向屏幕。这道题的要求是把标准输出,也就是fd=1,重定向到一个文件。
为此,我们首先用close命令把fd=1释放,也就是切断了它到标准输出的联系。之后使用dup把文件sortie的fd的指向,复制到fd=1的位置,此时已完成重定向,我们使用close把复制前的fd关掉即可。dup函数把参数中传入的fd复制到最小的,未被占用的fd位置,即我们刚刚关掉的1. 具体的命令描述请使用man命令。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void main(int argc, char** argv) { if(fork()==0) { //Section fils int fp = open("sortie", O_CREAT | O_WRONLY ); if(fp == -1) { perror(0); exit(0); } printf("Avant la redirectionn"); dup2(fp, 1); close(fp); printf("Après la redirectionn"); execlp("echo", "echo", "I want to appear in the stdout, but...", NULL); exit(0); } else { //pere } }
- 创建子进程并与父进程使用pipe进行简单的通信。
pipe通信是同步的,也就是说当一个进程使用read试图从pipe中读取数据时,如果此时pipe中没有数据,则此进程会被卡在这里,等待写入的数据。这一行为可以通过设置标志位更改,我们以后讨论。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void main(int argc, char** argv) { char a = 'a'; char b = 'b'; char rcv; int tube[2]; pipe(tube); if(fork()==0) { //Section fils printf("Fils : write 'a' au tube.n"); write(tube[1], &a, 1); printf("Fils : Sleep 5 secondes avant l'écriture.n"); sleep(5); printf("Fils : write 'b' au tube.n"); write(tube[1], &b, 1); exit(0); } else { //pere read( tube[0], &rcv, 1); printf("Père : read du tube :%c. Lire le char suivant.n", rcv); read( tube[0], &rcv, 1); printf("Père : read du tube :%c. n", rcv); } }
- 创建两个子进程A和B。将A的标准输出重定向到一个pipe的输入端,将B的标准输入定向到pipe的输出端。两个进程通过pipe进行通信。
提醒一下,pipe也是文件。只不过可以由多个进程同时进行读写。
#include<stdio.h> #include<unistd.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> void main(int argc, char** argv) { char a = 'a'; char b = 'b'; char rcv; int tube[2]; pipe(tube); if(fork()==0) { //Section fils dup2(tube[1], 1); close(tube[1]); printf("a"); //write(tube[1], &a, 1); exit(0); } else { //pere dup2(tube[0], 0); close(tube[0]); read( 0, &rcv, 1); //printf("Père : read du tube :%c. Lire le char suivant.n", rcv); //read( tube[0], &rcv, 1); printf("Père : read du tube :%c. n", rcv); } }
- 让我们再乱一些。双重重定向,两个pipe。两个子进程AB。将A的标准输出重定向到pipe1的输入端,标准输入定向到pipe2的输出端。将B的标准输出重定向到pipe2的输入端,标准输入定向到pipe1的输出端。两个进程通过pipe进行通信。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>void main(int argc, char** argv)
{
char a = 'a';
char b = 'b';
char rcv;
FILE* fd;
int tube[2];
int tube2[2];
pipe(tube);
pipe(tube2);
if(fork()==0) {
//Section fils
dup2(tube[1], 1);
dup2(tube2[0], 0);
close(tube[1]);
close(tube2[0]);printf("a");
fflush(stdout);
//read(0, &rcv, 1);
scanf("%c",&rcv);
fprintf(fdopen(2, "w"), "filsfilsbbbn");
//fd = fopen("fils.txt", "w");
//fd = fopen("fils.txt"