注:部分代码来至《unix高级环境编程》一书。
源码如下:
#include "apue.h"
#include <sys/wait.h>
int
main(void)
{
char buf[MAXLINE]; /* from apue.h */
pid_t pid;
int status;
printf("%% "); /* print prompt (printf requires %% to print %) */
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");
} else if (pid == 0) { /* child */
execlp(buf, buf, (char *)0);
err_ret("couldn't execute: %s", buf);
exit(127);
}
/* parent */
if ((pid = waitpid(pid, &status, 0)) < 0)
err_sys("waitpid error");
printf("%% ");
}
exit(0);
}
1、fgets函数使用方法说明
C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
声明
下面是 fgets() 函数的声明。
char *fgets(char *str, int n, FILE *stream)
参数
str -- 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
n -- 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
返回值
如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。
如果发生错误,返回一个空指针。
2、execlp 函数使用方法说明
execlp
从PATH 环境变量中查找文件并执行
定义:
int execlp(const char * file,const char * arg,……);
头文件:
#include<unistd.h>
说明:
execlp()会从PATH 环境变量所指的目录中查找符合参数file的文件名, 找到后便执行该文件, 然后将第二个以后的参数当做该文件的argv[0]、argv[1]……, 最后一个参数必须用空指针(NULL)作结束。
返回值:
如果执行成功则函数不会返回, 执行失败则直接返回-1, 失败原因存于errno 中。
相关函数:
fork, execl, execle, execv, execve, execvp
错误代码:
参考execve()。
示例:
#include<unistd.h>
main()
{
execlp("ls","ls","-al","/zhmc",(char *)0);
}
输出:
3、waitpid 函数使用方法说明
用于父进程等待子进程结束。
pid>0时,只等待进程ID等于pid的子进程,不管其它已经有多少子进程运行结束退出了,只要指定的子进程还没有结束,waitpid就会一直等下去。
pid=-1时,等待任何一个子进程退出,没有任何限制,此时waitpid和wait的作用一模一样。
pid=0时,等待同一个进程组中的任何子进程,如果子进程已经加入了别的进程组,waitpid不会对它做任何理睬。
pid<-1时,等待一个指定进程组中的任何子进程,这个进程组的ID等于pid的绝对值。
4、fork函数的使用说明
fork函数用来创建一个子进程。
每个进程都有它独自占有的PCB结构体,而我们通过fork。就是将进程复制了一份。
1.父进程和子进程是共享一块代码段的,也就是说同样的代码,父进程和子进程个执行一遍。
2.父进程和子进程数据独自占有,不共享。这就是为什么父进程和子进程同样的代码,却打印出两个不同的val值。
3.fork函数很神奇。它有两个返回值,父进程的返回值是子进程的id号,而子进程自己返回则返回零。失败返回-1.所以我们可以通过介绍fork()返回值来区分父进程子进程,还可以在子进程进行一些特殊操作。
注意:子父进程就像是交替运行一样。
5、下面创建2个子进程
#include "apue.h"
#include <sys/wait.h>
int main(void)
{
printf("before fork(), pid = %d\n", getpid());
pid_t p1 = fork();
if( p1 == 0 )
{
printf("in child 1, pid = %d\n", getpid());
return 0; //若此处没有return 0 p1 进程也会执行 pid_t p2=fork()语句
}
pid_t p2 = fork();
if( p2 == 0 )
{
printf("in child 2, pid = %d\n", getpid());
return 0; //子进程结束,跳回父进程
printf("hello world\n");//没有打印
}
int st1, st2;
waitpid( p1, &st1, 0);
waitpid( p2, &st2, 0);
printf("in parent, child 1 pid = %d\n", p1);
printf("in parent, child 2 pid = %d\n", p2);
printf("in parent, pid = %d\n", getpid());
printf("in parent, child 1 exited with %d\n", st1);
printf("in parent, child 2 exited with %d\n", st2);
return 0;
}
编译运行结果: