zoukankan      html  css  js  c++  java
  • 进程控制(一)

    进程控制(一)

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

    • 进程的基本概念

    • 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
    ",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
    ",count,getpid());
    	        else
    	        	printf("I am the parent process,the count is %d,my process ID is %d
    ",++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
    ",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
    ",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
    ",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
    ",count);
                if(!(child = vfork()))
                        {
                                int i;
                                for(i = 0;i < 100;i++)
                                {
                                        printf("this is son,the i is:%d
    ",i);
                                        if(i == 70)
                                        exit(1);
                                }
                                printf("this is son,his pid is:%d and the count is:%d
    ",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
    ",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$
  • 相关阅读:
    还需要做恰当的解读,此时你可能需要一些书:
    创业公司的架构演进史
    任务调度平台Cuckoo-Schedule
    ORACLE中死锁
    Action的模型绑定
    三次握手、四次握手、backlog
    Django框架
    扩展BootstrapTable的treegrid功能
    Identity Service
    Linux权限
  • 原文地址:https://www.cnblogs.com/myidea/p/4980978.html
Copyright © 2011-2022 走看看