前言
好久没学习了,最近都在忙着上班的事情,过年后这段时间感觉每天都有事情做,忙忙忙,学Linux感觉说实话,有点枯燥,比当初学FPGA还要枯燥。真的是毕业之后,再去学习的动力就下降很多吗。但是还是要坚持啊。。。
1.1 程序和进程的关系
- 程序:
简单来说程序是一个静态的文件,这个文件中包含了为特定任务的指令和序列。 - 进程:
进程是程序执行的具体实例。当一个程序被执行之后,它就是一个进程,直到程序运行结束,进程会被销毁。
在程序执行的过程中,它享有系统的资源, 至少包括进程的运行环境、CPU、外设、内存、进程ID等资源与信息。
同样的一个程序, 可以实例化为多个进程。
程序并不能单独执行,只有将程序加载到内存中,系统为他分配资源后才能够执行, 这种运行着的程序称之为进程, 每个进程都有自己单独的地址空间。
1.2 创建一个新进程
1.2.1 使用fork函数创建一个新进程
使用fork函数,相当于会将原来的进程进行复制,得到的新的进程和原始的进行基本一致。
fork函数在使用的时候,返回一个pid_t的类型的值,在子进程当中,这个返回值是0,在父进程中,这个返回值是子进程的PID号。
pid_t fork(void);
以一个具体的例子来演示一下:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t result;
printf("This is fork demo\n");
/*调用fork函数*/
result = fork();
if(result == -1)
{
printf("fork error!!!\r\n");
}
else if(result == 0)
{
printf("This is the child process,the result is %d, my PID is %d\r\n",result,getpid());
}
else
{
printf("This is the father process,the result is %d, my PID is %d\r\n",result,getpid());
}
return 0;
}
从执行的结果来看:
- 在fork函数之前的代码只会被执行一次
- 在for之后的代码会被执行两次
使用fork函数可以创建一个新的进程,但是这个创建的新的进程,和父进程几乎有一样的功能,几乎是将父进程进行拷贝得到的。在只从fork函数之后,fork函数之后的代码将会被执行两次,分别是在父进程当中执行和在子进程当中被执行。
可以根据fork函数的返回值来判断当前是父进程还是子进程,使用fork函数后,新进程和父进程都还是实现的相同的功能,想要更改子进程去执行不同的程序,可以使用exec函数来完成。
1.2.2 exec创建新进程
execl函数原型如下:
int execl(const char *path, const char *arg, ...)
path是新的程序所在的路径,arg是需要给这个程序传递的参数。
exec系列函数是直接将当前进程给替换掉的, 当调用exec系列函数后,当前进程将不会再继续执行, 因为当前进程已经被替换了。
exec系列函数函数是不会返回的,除非发生了错误。出现错误时,exec系列函数将返回-1,并且会设置错误变量error。
结合具体的例子来说明一下:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t result;
printf("This is execl demo\n");
/*调用fork函数*/
result = execl("/bin/ls", "ls", "-la",NULL);
if(result < -0)
{
printf("execl error!!!\r\n");
}
printf("Test Done!!!\r\n");
return 0;
}
从程序的执行结果来看,在使用了execl函数之后,原来的进程将会被替换,并且新进程没有出错的时候,新进程是不会返回的,从原来的函数当中,最后有一个打印提示测试结束的代码并没有被打印可以看出。
这样execl就实现了进程的替换。
2 退出一个进程
推出一个进程的方法比较简单,调用exit()函数或者_exit()函数就可以了。
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
pid_t result;
printf("This is fork demo\n");
/*调用fork函数*/
result = fork();
if(result == -1)
{
printf("fork error!!!\r\n");
}
else if(result == 0)
{
printf("This is the child process,the result is %d, my PID is %d",result,getpid());
_exit(0);
}
else
{
printf("This is the father process,the result is %d, my PID is %d",result,getpid());
exit(0);
}
return 0;
}
3. 等待进程退出
在使用fork函数新创建了一个进程的时候,有的时候,父进程希望知道子进程什么时候结束,或者想要知道,子进程结束的时候的状态,那么这个时候就需要使用wait函数,来获取子进程的推出状态。
wait函数原型:
pid_t wait(int *wstatus);
需要引入的头文件
#include <wait.h>
相关的例子:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <wait.h>
int main(void)
{
pid_t result;
pid_t child_pid ;
int status;
printf("This is fork demo\n");
/*调用fork函数*/
result = fork();
if(result == -1)
{
printf("fork error!!!\r\n");
}
else if(result == 0)
{
printf("This is the child process,the result is %d, my PID is %d\r\n",result,getpid());
sleep(3);
exit(0);
}
else
{
/*等待子进程结束*/
child_pid = wait(&status);
if(child_pid = result)
{
printf("The child process id:%d\r\n",child_pid);
printf("The child process exit value:%d\r\n",status);
}
else
{
printf("error\r\n");
}
printf("This is the father process,the result is %d, my PID is %d\r\n",result,getpid());
exit(0);
}
return 0;
}