循序渐进学unix——上机记录(六),exec
来源:互联网 发布:信息和数据的关系是 编辑:程序博客网 时间:2024/05/21 10:37
本次上机记录的主题是如何执行外部程序。Unix下有一组名为execxx()的函数:
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,.., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);
可以看出,这组函数的第一个参数是我们需要调用的程序文件名或详细路径,第二部分参数是为新程序传递的参数,在名为execlx的函数中,这些参数使用变长的参数列表传递,而在名为execvx的函数中这些参数使用一个参数数组传递。注意,参数的第一个永远是待调用的程序名称,最后一个乃是NULL。例如若想在程序中执行“ls -l”, 则应该调用:
execl("ls", "ls", "-l", NULL); 或
execv("ls", argv), 其中argv为一个包含"ls", "-l", NULL 的字符串数组。
另外execle中的e代表environment,表示希望传递的环境参数。
下面来看看这次的上机题:
1. 结合pipe和exec,写程序执行命令:"ls -l | tail -3 | wc -w"
这道题结合了管道和程序调用,要求有相对细致的理解。每当我们使用exec调用外部程序以后,当前进程就会被完全替换为新进程,所以我们需要3个进程分别执行ls,tail和wc命令,他们之间通过建立pipe实现数据的传递。
#define _GNU_SOURCE#include<stdlib.h>#include<unistd.h>#include<stdio.h>#include<fcntl.h> //pour le flag O_CLOEXECvoid main(){int val_fork;int pipe12[2];pipe(pipe12);//, O_CLOEXEC);if( (val_fork=fork())==0){//Fils1 lsclose(pipe12[0]);dup2(pipe12[1], 1);close(pipe12[1]);execlp("ls", "ls", "-l", NULL);exit(0);}int pipe23[2];pipe(pipe23);//pipe2(pipe23, O_CLOEXEC);if( (val_fork=fork())==0) {//Fils2 tail//ls -l -> tailclose(pipe12[1]);dup2(pipe12[0], 0);close(pipe12[0]);// tail -> wc close(pipe23[0]); dup2(pipe23[1], 1); close(pipe23[1]); execlp("tail", "tail", "-3", NULL); exit(0); }close(pipe12[0]);close(pipe12[1]);int pipe31[2];pipe(pipe31);//pipe2(pipe31, O_CLOEXEC);if( (val_fork=fork())==0) {//Fils3 wc //tail->wc close(pipe23[1]); dup2(pipe23[0], 0); close(pipe23[0]); // wc -> pere close(pipe31[0]); dup2(pipe31[1], 1); close(pipe31[1]); execlp("wc", "wc", "-w", NULL); exit(0); }close(pipe23[0]);close(pipe23[1]);close(pipe31[1]); dup2(pipe31[0], 0);close(pipe31[0]);int resultat;scanf("%d", &resultat);printf("Le résultat de la commande \"ls -l | tail -3 | wc -w\" est : %d.\n", resultat);exit(0);}
有一点如果不留意的话很容易出问题:一定要立即关闭不再使用的pipe。因为一些程序,比如tail,是当在pipe中读到EOF时才结束读入并开始执行的,所以如果没有及时关闭pipe会导致程序一直处于等待状态。
2, 这道题好像更像是关于signal的,补充在这里,权当复习吧。
创建一个子进程执行一项耗时的命令,并在5秒钟后将其杀死。主要涉及到alarm函数的使用。这一函数有一时间参数,可以在指定时间后向自身进程发送一个SIGALRM信号,进而我们可以通过这一信号的处理函数将子进程杀死。
#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<signal.h>int val_fork;void kill_fils( int signum){kill(val_fork, SIGKILL);printf("Je viens de tuer mon fils!\n");}void main(){if( (val_fork=fork()) == 0 ){while(1){printf("Je m'occupe sur un travail de durée longue!\n");sleep(1);}}else{signal(SIGALRM, kill_fils);alarm(5);wait(NULL);//Indispensable, sinon pb1: Père meurt, alarm() ne marche plus. pb2:On ne pourra pas terminer le fils en utilisant Ctrl-c, car le fils est détaché du terminal.}}
3,写程序证明:在执行exec函数之后,当前进程还能接受并处理之前配置过的信号吗?
根据exec的运行原理我们知道,调用这一函数后当前进程的上下文会完全被替换,所以之前所做的信号配置也就失效了。
#include<unistd.h>#include<stdio.h>#include<stdlib.h>#include<signal.h>int val_fork;void sigfunction( int signum){//kill(val_fork, SIGKILL);printf("Je viens de recevoir un signal!\n");}void main(){if( (val_fork=fork()) == 0 ){signal(SIGUSR1, sigfunction);execlp("sleep", "sleep", "5", NULL);}else{sleep(2);kill(val_fork, SIGUSR1);}}
- 循序渐进学unix——上机记录(六),exec
- 循序渐进学unix——上机记录(一)
- 循序渐进学unix——上机记录(二)
- 循序渐进学unix——上机记录(三)
- 循序渐进学unix——上机记录(四)
- 循序渐进学unix——上机记录(五),signal
- 循序渐进学unix——上机记录(八),Thread
- 循序渐进学unix——上机记录(七),socket
- 黑马程序员———循序渐进学编程
- 循序渐进学java基础笔记(1)——开山篇
- 循序渐进学习使用WINPCAP(六)
- 循序渐进学设计模式(一)
- UNIX环境编程学习笔记(20)——进程管理之exec 函数族
- unix exec
- 空闲时间学一个Linux命令(20)—— find 命令之 exec
- 老赵弱弱学习——unix环境高级编程(六)
- Unix C (六)
- Unix学习(六)
- loadrunner简单使用——HTTP,WebService,Socket压力测试脚本编写
- 浅谈Dynamic 关键字系列之一:dynamic 就是Object
- 新旧版hadoop的一些差别
- 编译型语言 和 解释型语言 的区别
- Apparent-time hypothesis
- 循序渐进学unix——上机记录(六),exec
- 浅谈Dynamic 关键字系列之二:调用属性,方法,字段
- SQL Server 跨库查询乱码问题
- 效率问题,Linq查询/多线程/反射/装箱相关
- 浅谈Dynamic 关键字系列之三:ExpandoObject, DynamicObject, DynamicMetaObject
- DataBase => O/R mapping Class => UI 解决方案(.NET/CS/WinForm/Linq)
- (google面试题)找出无序数组中连接和最大排序
- 浅谈Dynamic 关键字系列之四:dynamic为什么比反射快
- [WCF权限控制]ASP.NET Roles授权[上篇]