首页 理论教育 Linux系统编程实践:进程编程实验结果

Linux系统编程实践:进程编程实验结果

时间:2023-11-18 理论教育 版权反馈
【摘要】:④fork函数创建子进程后,父子进程是独立、同时运行的,并没有先后顺序。此外,子进程不会继承父进程的文件锁定和未处理的信号。如果没有子进程终止,调用阻塞,直到有一个子进程终止。pid=0:等待进程组识别码与目前进程相同的任何子进程。WUNTRACED:如果子进程进入暂停执行情况,则马上返回,但结束状态不予以理会。

Linux系统编程实践:进程编程实验结果

●实验目的:

学会fork、vfork函数的使用;

学会调用wait和waitpid函数。

●实验要求:

利用fork函数,编写一应用程序,在程序中创建一子进程,分别在父进程和子进程中打印进程ID;

使用vfork创建一子进程,让子进程睡眠1s,分别在父进程和子进程中打印进程ID,观察父子进程的运行顺序;

编写一应用程序,在程序中创建一子进程,父进程需等待子进程运行结束后才能执行。

●实验器材:

软件:安装了Linux的vmware虚拟机

硬件:PC机一台。

●实验步骤:

(1)fork函数的使用。

①编写实验代码fork_pid.c。

②编译应用程序fork_pid.c。

用gcc命令编译fork_pid.c后生成可执行文件fork_pid。

③运行应用程序。

④fork函数创建子进程后,父子进程是独立、同时运行的,并没有先后顺序。

(2)vfork创建子进程。

①编写实验代码vfork_pid.c。

②编译应用程序vfork_pid.c。

③运行应用程序。

可以看到,程序运行时会停1 s,然后分别打印出父子进程的ID。也就是说,子进程进来就阻塞1秒,但也没有先去运行父进程,而是让子进程运行完了之后才运行父进程。

(3)进程等待实验。

①编写代码文件wait.c。

②编译应用程序wait.c。

③运行程序wait。

④用fork创建子进程后,父子进程的执行顺序fork函数不能确定。可以用wait函数和waitpid函数使父进程阻塞等待子进程退出,来确保子进程先结束。

●上机报告要求:

1.填写实验中缺失的代码。

2.分析fork()、vfork()、wait()函数原型、功能、参数、返回值的意义。

#include<sys/types.h> /* 提供类型pid_t的定义 */

#include<unistd.h> /* 提供函数的定义 */

(1)pid_t fork(void);

功能:当fork()成功调用后,会创建一个新的进程,它几乎与调用fork()的进程完全相同。这两个进程都会继续运行,调用者进程从fork()返回后,还是照常运行。

返回值:fork调用的一个奇妙之处就是它仅仅被调用一次,却能够返回两次。它可能有三种不同的返回值:

在父进程中,fork返回新创建子进程的进程ID;

在子进程中,fork返回0;

如果出现错误,fork返回一个负值。fork出错可能有两种原因:①当前的进程数已经达到了系统规定的上限,这时errno值被设置为EAGAIN。②系统内存不足,这时errno值被设置为ENOMEM。(www.xing528.com)

(2)pid_t vfork(void);

参数:无

函数说明:

vfork()调用成功时,其执行结果与fork()是一样的,除了子进程会立即执行一次exce系统调用,或者调用_exit()退出。

vfork()会产生一个新的子进程,其子进程会复制父进程的数据与堆栈空间,并继承父进程的用户代码、组代码、环境变量、已打开的文件代码、工作目录和资源限制等。Linux 使用copy-on-write(COW)技术,只有当其中一进程试图修改欲复制的空间时才会做真正的复制动作。由于这些继承的信息是复制而来的,并非指相同的内存空间,因此子进程对这些变量的修改与父进程并不会同步。此外,子进程不会继承父进程的文件锁定和未处理的信号。注意,Linux不保证子进程会比父进程先执行或晚执行,因此编写程序时要留意死锁或竞争条件的发生。

返回值:如果vfork()成功,则在父进程会返回新建立的子进程代码(PID),而在新建立的子进程中则返回0;如果vfork 失败,则直接返回-1,失败原因存于errno中。

(3)wait(等待子进程中断或结束);

表头文件:

#include<sys/types.h>

#include<sys/wait.h>

定义函数:pid_t wait (int * status);

函数说明:调用wait()成功,会返回已终止子进程的pid;出错时,返回-1。如果没有子进程终止,调用阻塞,直到有一个子进程终止。如果有一个子进程已经终止了,调用会立即返回。

wait()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status 返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status可以设成NULL。若不为空,那它包含了关于子进程的一些其他信息。子进程的结束状态值请参考waitpid()。

返回值:如果执行成功,则返回子进程识别码(PID),如果有错误发生则返回-1。失败原因存于errno中。

(4)waitpid(等待子进程中断或结束);

表头文件:

#include<sys/types.h>

#include<sys/wait.h>

定义函数:pid_t waitpid (pid_t pid, int * status, int options);

函数说明:waitpid()会暂时停止目前进程的执行,直到有信号来到或子进程结束。如果在调用wait()时子进程已经结束,则wait()会立即返回子进程结束状态值。子进程的结束状态值会由参数status返回,而子进程的进程识别码也会一起返回。如果不在意结束状态值,则参数status可以设成NULL。

参数pid为欲等待的子进程识别码,其数值意义如下:

pid<-1:等待进程组识别码为pid绝对值的任何子进程。

pid=-1:等待任何子进程,相当于wait()。

pid=0:等待进程组识别码与目前进程相同的任何子进程。

pid>0:等待任何子进程识别码为pid的子进程。

参数option可以为0或下面的OR组合:

WNOHANG:如果没有任何已经结束的子进程,则马上返回,不予以等待。

WUNTRACED:如果子进程进入暂停执行情况,则马上返回,但结束状态不予以理会。

子进程的结束状态返回后存于status,底下有几个宏可判别结束情况:

WIFEXITED(status):如果子进程正常结束,则为非0值。

WEXITSTATUS(status):取得子进程exit()返回的结束代码,一般会先用WIFEXITED来判断是否正常结束才能使用此宏。

WIFSIGNALED(status):如果子进程是因为信号而结束,则此宏值为真。

WTERMSIG(status):取得子进程因信号而中止的信号代码,一般会先用 WIFSIGNALED来判断后才使用此宏。

WIFSTOPPED(status):如果子进程处于暂停执行情况,则此宏值为真。一般只有使用 WUNTRACED时才会有此情况。

WSTOPSIG(status):取得引发子进程暂停的信号代码,一般会先用WIFSTOPPED来判断后才使用此宏。

如果执行成功,则返回子进程识别码(PID);如果有错误发生,则返回返回值-1,失败原因存于errno中。

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈