zoukankan      html  css  js  c++  java
  • 0724------Linux基础----------进程1

    1.进程的基本概念

      1.1操作系统有三大抽象概念

        a)进程:程序的执行过程;

        b)文件: IO;

        c)虚拟内存:可用的地址空间;

      1.2 进程在内核中是一种数据结构 task_struct(定义见/usr/src/linux-headers-3.8.0-29/include/linux中1240行起)。

      1.3 进程由 PCB,代码段以及数据段组成,其中PCB位于内核空间,也就是上述的tsak_struct结构。

      1.4 虚拟内存的前面一部分为内核空间(1G),后面是用户空间。

      1.5 进程的运行模式有用户态内核态,以 read 为例,如果接受1000个字节,那么需要进行系统调用,由内核去接收 1000个字节,然后再返回用户态运行 read 的时候,把数据拷贝到用户空间

      1.6 用户态到内核态有两种方式,一是系统调用,触发trap指令陷入内核,二是中断,二者的区别在于前者是自愿的,后者是被动的。

    2.进程的状态

      2.1 进程的三种经典状态:

        a)就绪:准备完毕,随时等待调度;

        b)运行:占有CPU;

        c)阻塞:等待某一事件的发生。

      2.2 三种状态之间的转化

        a)就绪到运行:被CPU调度;

        b)运行到阻塞:执行了IO 等需要等待的系统调用,例如read;

        c)阻塞到就绪:等待的事件来临,例如read所等待的fd中有数据可读;

        d)运行到就绪:时间片到期或者被抢占

        e)这里不存在阻塞到运行:因为调度器总是从就绪队列里面挑选进程。

    3.僵尸进程和孤儿进程

      3.1 什么是僵尸进程?子进程退出,而父进程没有对其进行回收。这里注意:僵尸进程占用的不是用户空间的资源,子进程运行过程中申请的资源已经全部被回收,占用的是内核中的某些结构,如 PCB,它主要是留给父进程做参考,以便于父进程获取子进程的运行状态。

      3.2 僵尸进程程序示例。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    /*
     * 僵尸进程
     */
    int main(int argc, const char *argv[])
    {
        pid_t pid;
        if((pid = fork()) == 0){
            printf("in child, pid = %d, parent = %d
    ", getpid(), getppid());
        }
        else{
            sleep(20);
            printf("in parent, child = %d, pid = %d
     ", pid, getpid());
    
        }
        return 0;
    }

     

      3.3 孤儿进程:父进程先退出,子进程托管给init进程。

      3.4 孤儿进程示例。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    /*
    * 孤儿进程
    */
    int main(int argc, const char *argv[])
    {
    pid_t pid;
    if((pid = fork()) == 0){
    printf("in child, pid = %d, parent = %d
    ", getpid(), getppid());
    sleep(10);
    printf("in child, pid = %d, parent = %d
    ", getpid(), getppid());
    }
    else{
    sleep(1);
    printf("in parent, child = %d, pid = %d
     ", pid, getpid());
    }
    return 0;
    }

     

    4.fork和vfork函数

      4.1 利用fork产生的父子进程,地址空间是独立的。因为在传统的UNIX模型中,fork将父进程的地址空间复制了一份给子进程。

      4.2 fork程序示例。这里父子进程不共享全局变量,二者是独立的。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m);
            exit(EXIT_FAILURE);
        }while(0)
    /*
     * 父子进程的地址空间相互独立
     *
     */
    
    
    int g_val = 10;
    
    int main(int argc, const char *argv[])
    {
        pid_t  pid;
        pid = fork();
        if(pid == -1){
            ERR_EXIT("fork");
        }
        else if(pid == 0){
            sleep(3);
            printf("in child ,g_val = %d
    ", g_val);
        }
        else{
            g_val++;
            printf("in parent, g_val = %d
    ", g_val);
        }
        waitpid(-1, NULL, 0);
        return 0;
    }

      4.3 vfork 在产生子进程的时候,没有复制地址空间而是与父进程共享。vfork的目的就是为了在子进程中实行exec替换。程序示例如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define ERR_EXIT(m) 
        do { 
            perror(m);
            exit(EXIT_FAILURE);
        }while(0)
    /*
     * vfork
     */
    
    
    int g_val = 10;
    
    int main(int argc, const char *argv[])
    {
        pid_t  pid;
        pid = vfork();
        if(pid == -1){
            ERR_EXIT("fork");
        }
        else if(pid > 0){
            sleep(3);
            printf("in parent ,g_val = %d
    ", g_val);
        }
        else{
            g_val++;
            printf("in child, g_val = %d
    ", g_val);
            exit(EXIT_SUCCESS); //若不加 子进程会一直在父进程空间中执行
        }
        return 0;
    }

    5.atexit函数

      5.1 atexit 的作用是向系统注册一些函数,这些函数在程序退出的时候被调用,并且这些函数被调用的顺序与注册的顺序相反。程序示例如下。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void test1(){
        printf("test1...
    ");
    }
    
    void test2(){
        printf("test2...
    ");
    }
    
    void test3(){
        printf("test3...
    ");
    }
    int main(int argc, const char *argv[])
    {
        atexit(test1);
        atexit(test2);
        atexit(test3);
        printf("before return 
    ");
        return 0;
    }  

      5.2 exit 和 _exit 的区别

        a)exit 会清空 IO 缓冲区,后者不会;

        b)exit 会处理通过 atexit 注册的函数。

  • 相关阅读:
    Jmeter JAVA工程测试
    jsp页面img利用tomcat配置访问服务器绝对路径显示图片
    PostgreSQL模仿Oracle的instr函数
    linux清理内存命令
    Tomcat去除项目名称和端口号,直接使用ip地址访问项目的方法
    linux下重启oracle服务:监听器和实例
    RedHat Linux 9.0的安装+入门指南(图文并茂)
    linux命令详解之挂载光驱的方法
    jQuery download file
    fiddler
  • 原文地址:https://www.cnblogs.com/monicalee/p/3869228.html
Copyright © 2011-2022 走看看