linux学习--第五天(进程)

-进程

        -概念

           进程描述是一个程序执行过程,当程序执行后,执行过程开始,则进程产生;执行过程结束,则进程也就结束

        -进程的特点

           进程是一个独立的可调度的活动,由操作系统进行统一调度,相应的任务会被调度到cpu中进行执行

进程一旦产生,则需要分配相关资源,同时进程是资源分配的最小单位

        -进程与程序的区别

                1.程序是静态的,它是保存在磁盘上的指令的有序集合,没有任何执行的概念

                2.进程是一个动态的概念,它是程序执行的过程,包括了动态创建,调度和销毁的整个过程

        -并发与并行

                并行执行:表示多个任务可以同时执行,依赖于物理支持

                并发执行:在同一时间段由多个任务在同时进行,由操作系统的调度算法实现;如:时间片轮转

           时间片轮转

                特点:

        1.一个时间片的时间非常,由操作系统调度算法来实现每个时间片所执行的任务,一旦一个任务的时间片消耗完,则操作系统会切换到下个任务到CPU中执行

        2.如果没有执行结束,则等待下一次分配

        -Linux进程管理

                1.在Linux系统中,管理进程使用树型管理方式

                2.每一个进程都需要与其他某一个进程建立父子关系,对应的进程叫做父进程

                3.Linux系统会为每个进程分配id,这个id作为当前进程的唯一标识,当进程结束时,则会被回收

                4.进程的id与父进程的id分别通过getpid()getppid()来获取

        -进程的空间分配

                32位Linux系统中,会为每一个进程分配4G的空间,分为俩部分,高位1G为内核空间低位3G为用户空间4G空间为虚拟空间

        tips:

            1.当用户进程需要通过内核获取资源时,会切换到内核态运行,此时当前进程会使用内核空间资源

            2.用户切换的内核态运行时,主要是通过系统调用

        虚拟地址与物理地址

        虚拟地址:虚拟地址并不代表真实的内存空间,,而是一个用于寻址的编号

        物理地址:是指内存设备中真实存在的存储空间的编号

        关系:虚拟地址通过映射的方式建立与物理地址的关联,从而达到访问虚拟地址就可以访问到对应的物理地址

        使用虚拟地址的原因:

            1.直接访问物理地址,会导致地址空间没有隔离,很容易导致数据被修改

            2.通过虚拟地址可以实现每个进程空间都是独立的,操作系统会映射到不用的物理地址区间,在访问时互不干扰

        tips:1.进程栈的默认大小是8M,可以通过ulimit -s查看        

                 2.进程堆的大小小于3G

                 3.通过ulimit -u查看系统的最大进程数

        -进程的状态管理

                三态模型:运行态,就绪态,阻塞态

                三态模型图示:

                五态模型:新建态,终止态,运行态,就绪态,阻塞态

                五态模型图示

        经常使用的进程状态:

            1.运行态:此时进程正在运行或者准备运行都属于运行态

            2.睡眠态:此时进程在等待一个事件的发生或某种系统资源

                可中断睡眠:可以被信号唤醒或者等待事件或者资源就绪

                不可中断睡眠:只能等待特定的事件或者资源就绪

            3.停止态:进程停止接受某种处理,例如:gdb调试断点信息处理

            4.僵尸态:进程已经结束但是还没有释放进程资源

        --进程的相关命令

                ps  -ef:列出所有进程

                top:实时显示进程的信息

                top  -i:不显示任何闲置或无用的进程

                pstree:将所有的进程以树型结构的方式进行展示

                kill  -9:终止进程

        --创建进程

               通过调用fork()函数,则会产生一个新的进程,调用fork()函数的进程叫做父进程,产生的新的进程则为子进程

                通过fork()函数创建子进程,有如下特点:

                        1.父子进程并发执行子进程从fork()函数之后开始执行

                        2.父子进程的执行顺序由操作系统算法决定的,不是由程序本身决定

                        3.子进程会拷贝父进程地址空间的内容,包括缓冲区,文件描述符

                        (当子进程拷贝了父进程描述符后,则会共享文件状态与文件偏移量等信息

                       (子进程创建会拷贝父进程的地址空间,但是修改数据只会生效在子进程地址空间,说明父子空间的地址空间是相互独立的地址空间

        示例代码:

int main()
{
    pid_t pid = fork();
    if(pid==-1)
{
    perror("fork");
    return -1;
}
    printf("Hello fork.\n");
    return 0;
}

注:子进程:pid==0;父进程:pid>0

--进程多任务 

        -父子进程执行不同的任务

                使用fork()函数之后,会创建子进程,fork()之后的代码会在父子进程中都执行

                    1.如果父子进程执行相同的任务,则正常执行

2.如果父子进程执行不同的任务,则需要利用fork()函数返回值

         -创建多个进程

                在创建多个进程时,最主要的原则是由父进程统一创建,统一管理,不能递归创建

 --进程的退出

        在进程结束时,需要释放分配给进程的地址空间以及内核中产生的各种数据结构

                1.资源的释放需要通过exit函数或者_exit函数来实现

                2.在程序结束时,会自动调用exit函数

        -exit和_exit

            exit:结束进程,并刷新缓冲区

            _exit:结束进程,但不刷新缓冲区

        tips:

                在系统中定义了俩个状态值:EXIT_SUCCESS正常退出,EXIT_FAILURE异常退出

        -exit与_exit的不同

                 1._exit()属于系统调用,能够是进程停止运行,并释放空间以及销毁内核中的各种数据

                 2.exit()基于_exit()函数实现,属于库函数,会自动刷新I/O缓冲区

--进程的等待

        在子进程运行结束后(调用exit_exit),进程进入僵死状态,并释放资源,子进程在内核中的数据结构依然保留

        父进程调用wait()waitpid()函数等待子进程退出后,释放子进程遗留的资源

        -wait与waitpid

            wait让函数调用者进程进入睡眠状态,等待子进程进入僵死状态后释放资源并返回

            waitpid:功能与wait函数一样,但比wait函数更加强大,可以理解为wait()底层调用waitpid函数

            waitpid(-1,&staus,0); :waitpid使用阻塞的方式等待任意子进程退出

            waitpid(-1,NULL,0); :不关心状态值,子进程退出状态值的指针为NULL

--进程替换

        概念

            创建一个进程后,pid以及在内核中的信息保持不变,但进程所执行的代码进行替换

            应用场景:

                Linux终端应用程序,在执行命令时,通过创建一个进程,然后替换成对应命令的可执行程序

        -exec函数族

            在Linux系统中提供了一组用于进程替换的函数,共有6个:

                1.int execl(conest char* pathname,conest char* arg, .../*(char*),NULL*/);

                2.int execlp(const char *file, const char *arg, .../* (char *) NULL */);

                3.int execle(const char *pathname, const char *arg, .../*, (char *) NULL, char* const envp[ ] */);

                4.int execv(const char *pathname, char *const argv[ ]);

                5.int execvp(const char *file, char *const argv[ ]);

                6.int execvpe(const char *file, char *const argv[ ],char *const envp[ ]);

        示例代码:(通过execl函数执行ls -l命令

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    int ret;
    ret = execl("/bin/ls","ls","-l",NULL);
    if(ret == -1)
    {
        perror("execl");
        return -1;
    }
        return 0;
}

             输出结果:

     --进程间的通信-无名管道                     

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值