从标准输入读取命令并执行:
#include <apue.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char ** argv)
{
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; // replace newline with NULL
if ((pid = fork()) < 0) {
err_sys("fork error\n");
} else if (pid == 0) { // child, 子进程从这里执行
execlp(buf, buf, (char*)0);
err_ret("could not execute : %s\n", buf);
exit(127);
}
// parent, 父进程从这里执行
if ((pid = waitpid(pid, &status, 0)) < 0)
err_sys("waitpid error.\n");
printf("%% ");
}
return 0;
}
因为上面的gfets函数读入命令到buf时,缓冲区最后一个字符为’\n’,所以读入后,要把’\n’置换为NULL。
Unix通过fork函数创建一个新的进程,函数原型为:
pid_t fork (void);
pid_t为一个整数类型。
fork()的调用,会创建一个新的Unix进程,新进程是原进程的一个复制品,我们称呼原来的进程为父进程,新创建的进程为子进程。fork()调用一次,会得到两次返回。对于父进程,fork()会返回新的子进程的进程ID(非负数);对于子进程,fork()会返回0(分别在父子进程返回)。
fork()函数调用,会将父进程的地址空间完整地复制给子进程,调用后,父子进程各自拥有自己独立的进程空间。后续程序可根据pid_t的返回值,来确定父子进程的程序不同走向。
fork()返回负数,表示创建进程失败。
exec系列函数用于执行一个新的可执行文件。通常是在fork()后的子进程中调用,其作用是,把新的可执行文件加载到内存,来覆盖本进程的原有的进程空间,并跳到新可执行文件的起始位置重新执行。execlp()函数是exec()系列函数组中的一个。
父进程希望等待子进程终止,可以调用waitpid()函数实现。原型为:
pid_t waitpid(pid_t pid,int * status,int options);
pid指出子进程的ID,waitpid可以返回子进程的终止状态(status)。