Linux中C语言的编程有两个Windows环境下根本无须考虑的问题,关于管道和重定向的概念。
昨晚研究了一个通宵,关于fork()和execlp()函数,基本上用fork函数实现管道,用execlp来实现重定向。不过它们两个实现功能的方法都非常奇怪。
fork函数是让程序创建一个跟自己一模一样的副本,就跟当下流行的很多网络游戏中副本的概念差不多,昨晚在练习的时候忽然感到,这玩意儿又有点像WEB 编程中的表单自提交。在同一个程序里面写两套方案,运行时让其中的一套(安排在fork>=1的分支结构中)调用来自自身代码文件中的另一套方案 (安排在fork==0分支结构)乍一看这跟管道根本就挨不着边,我一开始也是觉得这样,就像一个进程又去调用了一个进程一样,不过另外调用的进程又是本 身,大脑里一团浆糊一样。那么请看代码吧:
/*
============================================================================
Name : fork_example.c
Author : newflypig
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int main(void) {
int i=1;
printf("in the begining,the value=%d ",i);
switch(fork()){
case -1:
fprintf(stderr,"%s ","fork error");
break;
case 0:
printf("child process start,at this time value=%d ",i);
i++;
printf("child process end,at this time value=%d ",i);
break;
default:
printf("parent process: value=%d ",i);
}
return 0;
}
运行结果是这样的:
in the begining,the value=1
child process start,at this time value=1
child process end,at this time value=2
parent process: value=1
可 以看到父进程首先设置i=1然后调用子进程,子进程一开始就有了父进程的i值,然后子进程在自己的基础上将i++了,子进程结束时输出了i=2。当程序返 回父进程时,子进程的改变并没有影响父进程中i的值,i依然为1。这个fork()的功能仅仅如此,有谁会想到让这个函数在Linux最具特色的管道机制 中大显伸手呢。
花开两朵,各表一枝。
下面看看重定向的概念:
先做一个演示程序:
/*
============================================================================
Name : execlp_example.c
Author : newflypig
Version :
Copyright : Your copyright notice
Description : Hello World in C, Ansi-style
============================================================================
*/
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
int main(void) {
int filedes;
if((filedes=open("dd.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))<0)
fprintf(stderr,"%s ","open file error");
close(1);
dup(filedes);
close(filedes);
execlp("ls","-l",(char * )0);
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
这是一段输出重定向的程序,为了解释方便,首先了解一下Linux中标准输入输出文件,Linux中基本上所有的元素都可以理解为文件,包括文件夹,设备等。程序中,首先使用close(1)关闭标准输出端子,{/*当然如果你想输入重定向的话可以关闭标准输入端子,它的序列是0;序列为3的端子是异常抛出端子,一般可以让此端子与输出设备保持一致。*/} , 然后使用dup函数将main函数的第一步所创建的名为dd.txt的文件设置为此程序的输出设备。接着要关闭该文件的连接,释放资源锁以便让程序来对此 文件进行读写。最后一步调用execlp函数进行命令的执行,这里执行了一个ls的命令,让当前目录下的所有文件名输出,execlp函数是可变参数函 数,第一个参数需要设置系统环境变量中所能获取的命令文件,或者自己设置绝对路径的命令文件,最后一个参数必须设置为空,以便标记这个函数的参数已经设置 完成,中间的所有参数设置为第一个命令的参数,如此段程序其实是执行ls -l这个命令。这样就将输出信息不直接打印到终端而输出到dd.txt文本文件中,完成输出重定向。
回到管道的问题上来。
如果将 刚刚讲得重定向技术配合fork()进程产生函数,便可以实现管道的作用了。这里说一下思路,就不给具体代码了,也就是设置两个全局的文件变量,将子进程 的输出重定向到其中一个文件变量,因为是全局变量,这个文件变量就被子进程彻底修改了,然后将父进程的输入重定向到刚刚子进程的输出,以此来完成 Linux中的管道机制。
不知各位看观对本人关于Linux中的管道以及重定向问题的看法是否认同,昨晚就看这两个函数的API和源代码了……
综上所述,一个毋庸置疑的结论:Linux编程比Windows编程艰巨而有趣多了。以前从来不高兴碰C语言,认为C++和java此类OO语言才是最人性化,最舒服的编程语言,这次初探C,感受到是另一种源于代码和算法的舒服感
昨晚研究了一个通宵,关于fork()和execlp()函数,基本上用fork函数实现管道,用execlp来实现重定向。不过它们两个实现功能的方法都非常奇怪。
fork函数是让程序创建一个跟自己一模一样的副本,就跟当下流行的很多网络游戏中副本的概念差不多,昨晚在练习的时候忽然感到,这玩意儿又有点像WEB 编程中的表单自提交。在同一个程序里面写两套方案,运行时让其中的一套(安排在fork>=1的分支结构中)调用来自自身代码文件中的另一套方案 (安排在fork==0分支结构)乍一看这跟管道根本就挨不着边,我一开始也是觉得这样,就像一个进程又去调用了一个进程一样,不过另外调用的进程又是本 身,大脑里一团浆糊一样。那么请看代码吧:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/37c8bf68cdc3cc81759c34160776bc53.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/717446ca04a6125dc5b6b54e0fa14ab4.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
运行结果是这样的:
in the begining,the value=1
child process start,at this time value=1
child process end,at this time value=2
parent process: value=1
可 以看到父进程首先设置i=1然后调用子进程,子进程一开始就有了父进程的i值,然后子进程在自己的基础上将i++了,子进程结束时输出了i=2。当程序返 回父进程时,子进程的改变并没有影响父进程中i的值,i依然为1。这个fork()的功能仅仅如此,有谁会想到让这个函数在Linux最具特色的管道机制 中大显伸手呢。
花开两朵,各表一枝。
下面看看重定向的概念:
先做一个演示程序:
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/a41954a27d6ad96fa2c2cf816e677448.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6a9c071a08f1dae2d3e1c512000eef41.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/0196c3df5ea9e936f21e9932cca91014.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
这是一段输出重定向的程序,为了解释方便,首先了解一下Linux中标准输入输出文件,Linux中基本上所有的元素都可以理解为文件,包括文件夹,设备等。程序中,首先使用close(1)关闭标准输出端子,{/*当然如果你想输入重定向的话可以关闭标准输入端子,它的序列是0;序列为3的端子是异常抛出端子,一般可以让此端子与输出设备保持一致。*/} , 然后使用dup函数将main函数的第一步所创建的名为dd.txt的文件设置为此程序的输出设备。接着要关闭该文件的连接,释放资源锁以便让程序来对此 文件进行读写。最后一步调用execlp函数进行命令的执行,这里执行了一个ls的命令,让当前目录下的所有文件名输出,execlp函数是可变参数函 数,第一个参数需要设置系统环境变量中所能获取的命令文件,或者自己设置绝对路径的命令文件,最后一个参数必须设置为空,以便标记这个函数的参数已经设置 完成,中间的所有参数设置为第一个命令的参数,如此段程序其实是执行ls -l这个命令。这样就将输出信息不直接打印到终端而输出到dd.txt文本文件中,完成输出重定向。
回到管道的问题上来。
如果将 刚刚讲得重定向技术配合fork()进程产生函数,便可以实现管道的作用了。这里说一下思路,就不给具体代码了,也就是设置两个全局的文件变量,将子进程 的输出重定向到其中一个文件变量,因为是全局变量,这个文件变量就被子进程彻底修改了,然后将父进程的输入重定向到刚刚子进程的输出,以此来完成 Linux中的管道机制。
不知各位看观对本人关于Linux中的管道以及重定向问题的看法是否认同,昨晚就看这两个函数的API和源代码了……
综上所述,一个毋庸置疑的结论:Linux编程比Windows编程艰巨而有趣多了。以前从来不高兴碰C语言,认为C++和java此类OO语言才是最人性化,最舒服的编程语言,这次初探C,感受到是另一种源于代码和算法的舒服感