前言
本文章主要介绍一种从标准输入读命令并执行的代码,以及对需要用到的函数fork、exec、waitpid等函数接口的介绍。
一、fork()函数
一个进程可以调用fork函数创建一个新进程。函数接口为:
#include<unistd.h>
pid_t fork(void);
由fork创建的进程被称为子进程,fork函数被调用一次,但返回两次,子进程返回值是0,而父进程的返回值则是新建子进程的进程ID,子进程成可以调用getppid()获得父进程的进程ID。
二、waitpid函数
用于父进程对子进程的回收,函数接口为:
#include<sys/wait.h>
pid_t waitpid(pid_t pid,int *statloc,int options);
三、exec函数
exec函数创建新的子进程后,子进程往往要调用一种exec函数以执行另一个程序,当进程调用一种exec函数时,改进程执行的程序完全被替换为新的程序,而新程序从其main函数开始执行。因为调用exec并不会创建新的进程,所以前后的进程ID并未改变。exec只是用磁盘上的一个新的程序替换了当前进程的正文段、数据段、堆段和栈段。有7种不同的exec函数可以供使用,用fork创建新进程->exec可以初始执行新的程序->exit函数、wait、waitpid函数处理终止和等待终止,下面是exec函数接口:
#include <unistd.h>
int execl(const char *pathname,const char *arg0,...);
int execv(const char *pathname,char *const argv[]);
int execle(const char *pathname,const char *arg0,...);
int execve(const char *pathname,char *const argv[],char *const envp[]);
int execvp(const char *filename,char *const argv[]);
int fexecve(int fd,char *const argv[],char *const envp[]);
四、代码例程
1.获取进程ID
代码如下(示例):
void unix_1_6_getpid(void)
{
printf("hello world from process ID %ld\n",(long)getpid());
exit(0);
}
2.从标准输入读命令并执行
代码如下(示例):
void unix_1_7_get_command_form_stdin_execute(void)
{
char buf[MAXLINE];
pid_t pid;
int status;
printf("%% ");
while(fgets(buf,MAXLINE,stdin) != NULL){
if(buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = 0;
if((pid=fork()) < 0)
err_sys("fork error");
else if(pid == 0){ //child
execlp(buf,buf,(char*)0);
err_ret("couldn't execute:%s",buf);
exit(127);
}
if((pid = waitpid(pid,&status,0))<0) //parent
err_sys("waitpid error");
printf("%% ");
}
exit(0);
五、代码说明
1.用标准IO函数fgets从标准输入一次读取一行,每一行都以换行符终止,后随一个null字节,要把换行符替换成null,这样才能符合execlp函数要求的参数以null结束而不是换行符。
2.编译后执行./a,out 然后输入ls、date、pwd、who即可。
总结
本文章主要是实现了标准输入读取命令并执行的程序,并简单介绍用到的相关函数。