app网站有哪些,wordpress插件开发教程视频,晋中网站seo,沈阳网页设计第1关#xff1a;进程等待
任务描述 通过上一个实训的学习#xff0c;我们学会了使用fork创建子进程#xff0c;在使用fork创建子进程的时候#xff0c;子进程和父进程的执行顺序是无法预知的。本关我们将介绍如何使得fork创建出来的子进程先执行#xff0c;随后父进程再…第1关进程等待
任务描述 通过上一个实训的学习我们学会了使用fork创建子进程在使用fork创建子进程的时候子进程和父进程的执行顺序是无法预知的。本关我们将介绍如何使得fork创建出来的子进程先执行随后父进程再执行。
本关任务学会在多进程中学会进程的等待处理。
相关知识 在上一个实训的学习我们知道使用fork可以创建一个进程并且创建的子进程其执行顺序可能在父进程前也可能在父进程后。因此这是由于fork创建的进程是由操作系统调度器来决定执行顺序的。如果当子进程在父进程前结束则内核会把子进程设置为一个特殊的状态。这种状态的进程叫做僵死进程(zombie)。尽管子进程退出的时候内核释放该进程所有的资源包括打开的文件占用的内存。但是仍然保留了一些信息(如进程号pid退出状态 运行时间等)。只有父进程获取了子进程的这些信息后子进程才会彻底的被销毁否则一直保持僵死状态。如果系统中产生大量的僵尸进程将导致系统没有可用的进程号从而导致系统不能创建新的进程。
Linux处理僵死进程的方法之一是使用进程等待的系统调用wait和waitpid来使得父进程获取子进程的终止信息。
wait函数和waitpid函数是系统调用函数因此使用man 2 函数名来查看其使用方法。
wait函数使用方法 wait函数的具体的说明如下
需要的头文件如下
#include sys/types.h
#include sys/wait.h wait函数格式如下
pid_t wait(int *status); 参数说明 参数status是一个整数指针当子进程结束时将子进程的结束状态字存放在该指针指向的缓存区。利用这个状态字需要时可以使用一些由 Linux 系统定义的宏来了解子程序结束的原因。这些宏的定义与作用如下: 函数返回值说明 调用成功时返回值为被置于等待状态的进程的 pid执行失败返回-1并设置错误代码errno。 案例演示1: 编写一个程序使用fork函数与wait函数结合创建一个新进程使得新创建的子进程在父进程前执行。详细代码如下所示
#include stdio.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include stdlib.h
#include string.h
#include errno.h
int main()
{pid_t pid;pid fork();if(pid -1){//创建进程失败printf(创建进程失败(%s)!\n, strerror(errno));return -1;}else if(pid 0){//子进程sleep(2);printf(This is child process\n);exit(1);}else{//父进程int status;if(wait(status) ! -1){if(WIFEXITED(status))printf(子进程正常退出退出代码%d\n, WEXITSTATUS(status));}printf(This is parent process\n);exit(0);}
} 将以上代码保存为waitProcess.c文件编译执行。可以看到执行waitProcess程序后尽管子进程使用sleep睡眠了2秒还是子进程先执行然后父进程才执行。这就是wait的作用使得父进程一直等待子进程执行结束后才继续执行。
waitpid函数使用方法 waitpid函数的具体的说明如下
需要的头文件如下
#include sys/types.h
#include sys/wait.h waitpid函数格式如下
pid_t waitpid(pid_t pid, int *status, int options); 参数说明 pid用于指定所等待的进程。其取值和相应的含义如下所示 参数option则用于指定进程所做操作。其取值和相应的含义如下所示 参数status是一个整数指针当子进程结束时将子进程的结束状态字存放在该指针指向的缓存区。 函数返回值说明 调用成功时返回收集到的子进程的进程pid当设置选项WNOHANG而调用中waitpid发现没有已退出的子进程可收集则返回0执行失败返回-1并设置错误代码errno。 案例演示1: 编写一个程序使用fork函数与waitpid函数结合创建一个新进程使得新创建的子进程在父进程前执行。详细代码如下所示
#include stdio.h
#include sys/types.h
#include sys/wait.h
#include unistd.h
#include stdlib.h
#include string.h
#include errno.h
int main()
{pid_t pid;pid fork();if(pid -1){//创建进程失败printf(创建进程失败(%s)!\n, strerror(errno));return -1;}else if(pid 0){//子进程sleep(2);printf(This is child process\n);exit(1);}else{//父进程int status;if(waitpid(-1, status, 0) ! -1){if(WIFEXITED(status))printf(子进程正常退出退出代码%d\n, WEXITSTATUS(status));}printf(This is parent process\n);exit(0);}
} 将以上代码保存为waitpidProcess.c文件编译执行。可以看到执行waitpidProcess程序后尽管子进程使用sleep睡眠了2秒还是子进程先执行然后父进程才执行。waitpid函数可以实现与wait函数相同的功能。
编程要求 本关的编程任务是补全右侧代码片段中Begin至End中间的代码具体要求如下
补全waitProcess函数等待子进程结束并且返回子进程的退出的代码。 测试说明 本关的测试需要用户在右侧代码页中补全代码然后点击评测按钮平台会自动验证用户是否按照要求去检测结果。
开始你的任务吧祝你成功 解答
#include unistd.h
#include sys/types.h
#include sys/wait.h
#include stdio.h/************************* 返回值: 调用成功且子进程正常退出返回退出代码否则返回-1
*************************/
int waitProcess()
{int status -1;/********** BEGIN **********/pid_t pid;pid fork();if(pid -1){//创建进程失败return -1;}else if(pid 0){//子进程sleep(2);printf(This is child process\n);exit(1);}else{//父进程int status;if(waitpid(-1, status, 0) ! -1){if(WIFEXITED(status))return WEXITSTATUS(status);}exit(0);}/********** END **********/return status;
}
第2关进程创建操作-exec函数族
任务描述 在上一个实训中我们学习使用fork函数创建新进程本关我们将介绍如何另一种创建新进程的库函数。
本关任务学会使用C语言在Linux系统中使用exec族的系统调用创建一个新的进程。
相关知识 在上一个实训中提到fork函数创建的子进程可以通过调用exec函数族来正确退出。其原理是使用exec函数族可以执行一个新的程序并且以新的子进程来完全替换原有的进程地址空间。
exec函数族的作用是根据指定的文件名找到可执行文件并用它来取代调用进程的内容换句话说就是在调用进程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件也可以是任何Linux下可执行的脚本文件。
通常exec函数族用来与fork函数结合一起使用。使用fork函数创建一个子进程然后在子进程中使用exec函数族来执行一个新的程序。当在由fork创建的子进程中使用exec函数族来执行新程序时子进程的地址空间会被新执行的程序完全覆盖并且此时fork的父进程与子进程地址空间被分离开也就是使用exec函数族创建的新程序不会对fork的父进程造成任何影响。
exec函数族是库函数因此使用man 3 exec来查看其使用方法。
使用exec函数族创建进程 exec函数族的具体的说明如下
需要的头文件如下
#include unistd.h 函数族格式如下
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, ... /*, (char *) NULL, 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[]); 参数说明 1、函数名中含有字母l的函数其参数个数不定。其参数由所调用程序的命令行参数列表组成最后一个NULL表示结束。
2、函数名中含所有字母v的函数则是使用一个字符串数组指针argv指向参数列表这一字符串数组和含有l的函数中的参数列表完全相同也同样以NULL结束。 3、函数名中含有字母p的函数可以自动在环境变量PATH指定的路径中搜索要执行的程序。因此它的第一个参数为file表示可执行函数的文件名。而其他函数则需要用户在参数列表中指定该程序路径其第一个参数path 是路径名。路径的指定可以是绝对路径也可一个是相对路径。但出于对系统安全的考虑建议使用绝对路径而尽量避免使用相对路径。 4、函数名中含有字母e的函数比其他函数多含有一个参数envp。该参数是字符串数组指针用于制定环境变量。调用这两个函数时可以由用户自行设定子进程的环境变量存放在参数envp所指向的字符串数组中。这个字符串数组也必须由NULL结束。其他函数则是接收当前环境。 函数返回值说明 只有当函数执行失败时exec函数族才会返回-1并设置错误代码errno。当执行成功时exec函数族是不会返回任何值。 案例演示1: 编写一个程序使用fork函数与exec函数族结合创建一个新进程并在子进程中执行touch testFile命令创建一个testFile文件在父进程中返回进程ID。详细代码如下所示
#include stdio.h
#include sys/types.h
#include unistd.h
#include stdlib.h
#include string.h
#include errno.h
int main()
{pid_t pid;pid fork();if(pid -1){//创建进程失败printf(创建进程失败(%s)!\n, strerror(errno));return -1;}else if(pid 0){//子进程if(execlp(touch, touch, testFile, NULL) 0){//执行execlp函数失败exit(-1);}}else{//父进程printf(当前进程为父进程pid(%d)ppid(%d)\n, getpid(), getppid());}//如果执行execlp成功则以下代码只会被父进程执行exit(0);
} 将以上代码保存为execlProcess.c文件编译执行。可以看到执行execlProcess程序后在当前目录下创建了一个名为testFile的文件。
编程要求 本关的编程任务是补全右侧代码片段中Begin至End中间的代码具体要求如下
补全execlProcess函数使用fork函数创建进程并在子进程中调用创建一个名为testDir的目录在父进程中输出Parent Process字符串。 测试说明 本关的测试需要用户在右侧代码页中补全代码然后点击评测按钮平台会自动验证用户是否按照要求去检测结果。
开始你的任务吧祝你成功 解答
#include stdio.h
#include sys/types.h
#include unistd.h
#include stdlib.h
#include string.h
#include errno.h/************************* 提示: 在子进程中如果执行exec函数失败要使用exit函数正确退出子进程
*************************/
int execlProcess()
{pid_t pid vfork();if(pid -1){printf(创建子进程失败(%s)\n, strerror(errno));return -1;}else if(pid 0){//子进程/********** BEGIN **********/if(execlp(touch, touch, testFile, NULL) 0){//执行execlp函数失败exit(-1);}/********** END **********/}else{//父进程/********** BEGIN **********/printf(Parent Process);/********** END **********/}
}
第3关进程创建操作-system
任务描述 在上一关中我们学习使用exec函数族执行新的程序本关我们将介绍如何另一种执行新的程序的库函数。
本关任务学会使用C语言在Linux系统中使用system库函数来执行一个新的程序。
相关知识 在上一关中我们学习了如何使用vfork结合exec函数族来执行一个新的程序。在Linux系统中提供了另一个库函数来实现执行一个新的程序。那就是system函数。
system函数是一个和操作系统相关紧密的函数。用户可以使用它来在用户自己的程序中调用系统提供的各种命令。因此system函数使用起来是很方便的用户可以在自己的程序中很方便地实现一些功能。
执行系统的命令行,其实也是调用程序创建一个进程来实现的。实际上system函数的实现正是通过调用fork、exec和waitpid函数来完成的。详细的实现思路是首先使用fork创建一个新的进程并且在子进程中通过调用exec函数族来执行一个新程序在父进程中通过waitpid函数等待子进程的结束同时也获取子进程退出代码。
system函数是库函数因此使用man 3 system来查看其使用方法。
使用system函数执行程序一个新程序 system函数的具体的说明如下
需要的头文件如下
#include stdlib.h 函数格式如下
int system(const char *command); 参数说明 command需要被执行的命令
函数返回值说明 执行成功返回值是执行命令得到的返回状态如同wait的返回值一样。执行失败时返回的值分为以下几种情况执行system函数时它将调用fork、exec和waitpid函数。其中任意一个调用失败都可以使得system函数的调用失败。如果调用fork函数出错则返回值为-1errno被设置为相应错误如果调用exec时失败则表示shell无法执行所设命令返回值为shell操作的返回值如果调用waitpid函数失败,则返回值也为-1errno被置为相应值。
案例演示1: 编写一个程序使用system函数来执行touch testFile命令创建一个testFile文件。详细代码如下所示
#include stdio.h
#include string.h
#include errno.h
int main()
{int ret system(touch testFile);if(ret -1){printf(执行 touch testFile 命令失败(%s)\n, strerror(errno));return -1;}return 0;
} 将以上代码保存为system.c文件编译执行。可以看到执行system程序后在当前目录下创建了一个名为testFile的文件。
编程要求 本关的编程任务是补全右侧代码片段中Begin至End中间的代码具体要求如下
补全createProcess函数使用system函数创建一个名为testDir的目录(使用system(mkdir testDir)创建目录 调用成功返回命令的状态码失败返回-1)。 测试说明 本关的测试需要用户在右侧代码页中补全代码然后点击评测按钮平台会自动验证用户是否按照要求去检测结果。
开始你的任务吧祝你成功 解答
#include stdlib.h
#include stdio.h
#include string.h
#include errno.h/************************* 返回值: 调用成功返回命令的状态码失败返回-1
*************************/
int createProcess()
{int ret -1;/********** BEGIN **********/retsystem(mkdir testDir);if(ret -1){return -1;}/********** END **********/return ret;
}