进程控制(一)

进程控制(一)

主要介绍两个方面的内容:

  • 进程的基本概念

  • Linux下进程控制的相关函数调用(fork和vfork)

进程的基本概念

要理解进程的基本概念,首先要理解

Linux是一个多用户多任务的操作系统;

	多用户:是指多个用户可以同时使用一台计算机
	多任务:Cpu的运行时间分为多个时间片, 每一个任务执行一个时间片,直到时间片所标注的时间点,它都必须退出cpu资源,让其他任务获得cpu资源执行,直到某个任务全部执行完,这个任务才会从cpu任务队列中退出。(即Linux使用分时管理的方法使所有任务共享系统资源)

Linux系统上所有运行的东西都可以称之为一个进程。

一个比较正式的定义:在自身的虚拟地址空间运行的一个单独的程序

进程 不等于 程序

进程是由程序产生的
程序是静态的命令集合,不占用系统的运行资源
进程是一个随时可能发生变化的、动态的、使用系统运行资源的程序
一个程序可以启动多个进程

进程和程序间的关系可以想象成戏剧和剧本的关系

一个程序可以对应多个进程——>一个剧本可以拿来拍摄多部电视剧
一个进程只能对应一个程序——>一部电视剧只能使用一个剧本

进程的四个要素:

  • 要有一段程序供该程序运行
  • 进程专用的系统堆栈空间
  • 进程控制块(稍后会提到),在Linux中的具体实现是task_struct结构
  • 有独立的存储空间

线程

当一个进程缺少四要素的其中一个条件时,我们称其为线程

  • Linux中所有进程都相互联系,除了初始化进程外,所有进程都有一个父进程

  • Linux中所有进程都是由一个进程号为1的init进程衍生而来

  • 我们在shell下执行程序启动的进程就是shell的子进程

  • 每一个进程都可以再启动自己的子进程,这样就形成了一棵进程树,每个进程都是树中的一个节点,树的根是init

  • Linux中,每个进程在创建时都会被分配一个数据结构,称为进程控制块(Process Control Block)。PCB是系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程。
    进程与PCB是一一对应的关系

函数getpid获取进程ID

函数定义:

#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void)

函数描述:

无参数
返回值为进程的ID

代码描述:

#include <sys/types.h>(定义了linux系统中数据类型的头文件)
#include <unistd.h>
main()
{
	printf("The current process ID is %d\n",getpid());
}

函数定义中,getpid的类型为pid_t,从代码描述的输出函数中,getpid的类型为%d,即int类型,由此可知,pid_t和int是兼容的,因为#include <sys/types.h>定义了linux中数据类型的头文件,故调用get_pid的时候,可以省略#include <sys/types.h>这个头文件

进程控制的相关函数

fork和vfork

1 fork

(1)函数原型:

#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);

(2)返回:若成功,父进程中返回子进程ID,子进程中返回0,若出错则返回-1

(3)函数解析

  • fork:复制一个进程(当一个进程调用它,完成后就出现两个几乎一模一样的进程)
  • 子进程:由fork创建的新进程被称为子进程(child process),将原来的进程称为父进程(parent process)
  • 子进程从父进程得到数据段和堆栈段的拷贝,这些需要分配新的内存;对于只读的代码段,通常使用共享内存的方式访问
  • fork函数被调用一次,但返回两次,两次返回的区别是子进程的返回值是0,而父进程的返回值是新子进程的进程ID
  • fork返回后,父子进程都从调用fork函数的下一条语句开始执行
  • 一般来说,在fork之后是父进程先执行还是子进程先执行是不确定的,这取决于内核所使用的调度算法
  • 现在很多的linux系统中,并不是做一个父进程数据段和堆栈的完全拷贝,因为在fork之后经常跟随着exec
  • linux中,创建新进程的方法只有一个,即fork。

(4)fork函数的使用:

	#include <stdlib.h>
	#include <sys/types.h>
	#include <unistd.h>
	#include <stdio.h>
	int main(void)
	{
	        int count = 0;
	        pid_t pid;/*此时仅有一个进程*/
	        pid = fork();/*此时已经有两个进程同时运行*/
	        if(pid < 0)
	        {
	        	printf("error in fork!");
	       	 	exit(1);
	        }
	        else if(pid == 0)
	        	printf("I am the child process,the count is %d,my process ID is %d\n",count,getpid());
	        else
	        	printf("I am the parent process,the count is %d,my process ID is %d\n",++count,getpid());
	        return 0;
	}



	运行结果:I am the parent process,the count is 1,my process ID is 12442
	hyx@hyx-virtual-machine:~/test$ I am the child process,the count is 0,my process ID is 12443

    从结果可以看出:两个进程有不同的process ID和count值,由此得知,他们占用不同的内存资源。 

2 vfork

(1)函数原型:

#include <sys/types.h>
#include <unistd.h>
pid_t vfork(void);

(2)返回:与fork相同,若成功,父进程返回子进程ID,子进程返回0,出错则返回-1

(3)fork与vfork的区别

  • fork要拷贝父进程的数据段;vfork不需要完全拷贝父进程的数据段,在子进程没有调用exec或exit之前,子进程与父进程共享数据段
  • fork不对父子进程的执行次序进行限制;vfork调用中,子进程先运行,父进程挂起,直到子进程调用了exec或exit之后,父子进程的执行次序才不再有限制。
  • 事实上,vfork创建出来的并不是真正意义上的进程,二是一个线程,因为它缺少了进程的四要素的第4项——独立的内存资源

(4)
以下程序说明vfork创建的子进程与父进程之间是共享数据段的,vfork_test1.c代码如下:

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main(void)
	{
		int count = 1;
		int child;
		printf("before creat son,the father's count is:%d\n",count);
		child = vfork();/*此时已经有两个进程在同时运行*/
		if(child < 0)
			{
				printf("error in vfork!");
				exit(1);
			}/*fork出错退出*/
		if(child==0) /*子进程*/
			{
				printf("this is son,his pid is:%d and the count is:%d\n",getpid(),count++);
				exit(1);
			}
		else /*父进程*/
			{
				printf("after son,this is father,his pid is:%d and the count is:%d,and the child is:%d\n",getpid(),count,child);
			}
		return 0;
	}

运行结果:
hyx@hyx-virtual-machine:~/test$ ./vfork_test
before creat son,the father's count is:1
this is son,his pid is:12834 and the count is:2
after son,this is father,his pid is:12833 and the count is:2,and the child is:12834

一点理解
我们只对子进程的count做了++,并没有对父进程的count做++,但子进程和父进程的count值都是2,由此可知,子进程和父进程共享数据段(或内存单元),count变量在父子进程中存储在同一个内存单元

(5)
以下代码说明vfork创建的子进程导致父进程挂起,vfork_test2.c代码如下:

	#include <sys/types.h>
	#include <stdlib.h>
	#include <stdio.h>
	#include <unistd.h>
	int main(void)
    {
            int count = 1;
            int child;
            printf("before create son,the father's count is:%d\n",count);
            if(!(child = vfork()))
                    {
                            int i;
                            for(i = 0;i < 100;i++)
                            {
                                    printf("this is son,the i is:%d\n",i);
                                    if(i == 70)
                                    exit(1);
                            }
                            printf("this is son,his pid is:%d and the count is:%d\n",getpid(),++count);
                            exit(1);
                    }
            else
            {
            printf("after son,this is father,his pid is:%d and the count is:%d,and the child is:%d\n",getpid(),count,child);
            }
            return 0;
    }

运行结果:

hyx@hyx-virtual-machine:~/test$ ./vfork_test2
before create son,the father's count is:1
this is son,the i is:0
this is son,the i is:1
this is son,the i is:2
this is son,the i is:3
this is son,the i is:4
this is son,the i is:5
this is son,the i is:6
this is son,the i is:7
this is son,the i is:8
this is son,the i is:9
this is son,the i is:10
this is son,the i is:11
this is son,the i is:12
this is son,the i is:13
this is son,the i is:14
this is son,the i is:15
this is son,the i is:16
this is son,the i is:17
this is son,the i is:18
this is son,the i is:19
this is son,the i is:20
this is son,the i is:21
this is son,the i is:22
this is son,the i is:23
this is son,the i is:24
this is son,the i is:25
this is son,the i is:26
this is son,the i is:27
this is son,the i is:28
this is son,the i is:29
this is son,the i is:30
this is son,the i is:31
this is son,the i is:32
this is son,the i is:33
this is son,the i is:34
this is son,the i is:35
this is son,the i is:36
this is son,the i is:37
this is son,the i is:38
this is son,the i is:39
this is son,the i is:40
this is son,the i is:41
this is son,the i is:42
this is son,the i is:43
this is son,the i is:44
this is son,the i is:45
this is son,the i is:46
this is son,the i is:47
this is son,the i is:48
this is son,the i is:49
this is son,the i is:50
this is son,the i is:51
this is son,the i is:52
this is son,the i is:53
this is son,the i is:54
this is son,the i is:55
this is son,the i is:56
this is son,the i is:57
this is son,the i is:58
this is son,the i is:59
this is son,the i is:60
this is son,the i is:61
this is son,the i is:62
this is son,the i is:63
this is son,the i is:64
this is son,the i is:65
this is son,the i is:66
this is son,the i is:67
this is son,the i is:68
this is son,the i is:69
this is son,the i is:70
after son,this is father,his pid is:20575 and the count is:1,and the child is:20576
hyx@hyx-virtual-machine:~/test$
posted @ 2015-11-20 15:42  adacn  阅读(275)  评论(0编辑  收藏  举报