—进程控制 上篇
Posted the_scent_of_th_soul
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了—进程控制 上篇相关的知识,希望对你有一定的参考价值。
linux系统的一个重要特点就是:可以同时启动多个进程。那么什么是进程呢?
(一)进程概念:进程简单地讲就是运行中
的程序。它是一个动态的实体
,是程序的一次执行过程。另外,进程是操作系统资源分配的基本单位。
进程与程序不同,程序是一些保存在硬盘上的可执行的代码
,是静态的。
(二)进程操作:
每个进程都由ID号标识,进程被创建时系统会为其分配一个唯一
的进程ID。
1.创建进程
:除了极少数以特殊方法创建的进程(如init进程)外,系统调用fork是创建一个新进程的唯一方法。进程调用fork函数就创建了一个子进程。
fork函数的声明及其功能如下:
pid_t fork(void); /*调用一次返回两次*/
int main(void)
pid_t pid;
char * msg;
int k;
pid=fork(); /*Create a child process*/
switch(pid)
case 0:msg="child process is running";
k=3;
break;
case -1:printf("process creation is fail\\n");
break;
default :msg="parent process is running";
k=5;
break;
while(k>0)
puts(msg);
sleep(1);
k--;
exit(0);
从输出上可以看到,switch语句被执行了两次,一次是在子进程中执行,一次是在父进程中执行。fork返回值有两个,一个是父进程调用fork函数后的返回值:刚建的子进程的ID,另一个是子进程中fork函数的返回值:0。
一般来说,fork之后
是子进程还是父进程先执行是不确定的,这取决于内核所使用的调度算法。除非某进程的优先级比其他进程高,否则操作系统让所有进程享有同等执行权。由while语句输出的内容可以发现,父子进程其实是交替执行的
。
注:
可以用ps命令查看进程的当前状态。
vfork函数也可以用来创建一个新进程,它其实是调用了fork函数。与fork的异同点主要如下:
(1)vfork与fork一样,都是调用一次,返回两次。
(2)fork创建的子进程完全复制父进程的资源,子进程独立于父进程,具有良好的并发性。vfork创建的子进程共享父进程的地址空间,完全运行在父进程的地址空间上,子进程对该地址空间中任何数据的修改同样为父进程所见。
(3)fork创建的子进程运行的先后取决于调度算法,vfork保证子进程先运行。
个人觉得创建守护进程涉及的内容比较多,所以有关守护进程的内容我将在下篇说明,这里暂时先不提及。
2.进程退出
:
在 main 函数中中执行return
调用exit或者_exit函数 /*正常退出*/
调用about函数
进程接受某个使程序终止的信号 /*异常退出*/
不管哪一种退出方式,最终都会执行内核中的同一段代码。这段代码用来关闭进程所有已打开的文件描述符,释放它所占用的内存和其他资源。
另外,父子进程终止的先后顺序不同会产生不同的结果,具体将在下篇和守护进程一块儿说明。
3.执行新程序
:
几个进程同时执行一个应用程序通常用处不大,常见的使用方法是子进程在被fork后通过调用exec函数执行另外一个程序。
系统调用exec用于执行一个可执行程序以代替当前进程的执行映像。exec调用并没有生成新进程。一个进程一旦调用exec函数,它本身就 ”死亡了“,系统把代码段替换成新的程序的代码段,废弃原有的数据段和堆段,并为新程序重新分配,唯一保留的就是进程ID。也就是说,对于系统而言,还是同一个进程,不过执行的已经是另外一个程序了。
exec函数族里有很多不同定义的函数,但是无论是哪一个exec函数,事实上都是将可执行程序的路径、命令行参数、和环境变量3个参数传递给可执行程序的main函数。
引入一下环境变量的概念:包括用户的主目录、终端类型、当前目录等,它们定义了用户的工作环境,所以称为环境变量。下面是简单的环境变量应用的代码:
//extern char ** environ;
int main(int argc, char *argv[], char ** environ)
int i;
printf("Argument\\n");
for(i=0; i<argc; i++)
printf("argv[%d] is %s\\n", i, argv[i]);
printf("Environment\\n");
for(i=0; environ[i] != NULL; i++)
printf("%s\\n", environ[i]);
可以把第一行的注释去掉,把main函数的第三个参数去掉。会发现,得到的结果是一样的。
以上是关于—进程控制 上篇的主要内容,如果未能解决你的问题,请参考以下文章