连考了两周试,好久不见……
这次上机主题是“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 redirection\n");
dup2(fp, 1);
close(fp);
printf("Après la redirection\n");
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进行通信。
#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"), "filsfilsbbb\n");
//fd = fopen("fils.txt", "w");
//fd = fopen("fils.txt", O_CREAT | O_WRONLY);
//fprintf(fd, "Fils : receive b\n");
//write(tube[1], &a, 1);
exit(0);
} else {
//pere
dup2(tube[0], 0);
dup2(tube2[1], 1);
close(tube[0]);
close(tube2[1]);
//read( 0, &rcv, 1);
scanf("%c", &rcv);
fprintf(stderr, "perepereaaa\n");
//fd = fopen("pere.txt", O_CREAT | O_WRONLY);
// fd = fopen("pere.txt", "w");
// fprintf(fd, "receive a\n");
printf("b");
//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);
}
}
哦了,先贴到这,后半部分晚些时候再上。