Jeff的linux环境编程第四天:进程(我的offer在哪里!)

7 篇文章 0 订阅
7 篇文章 0 订阅

进程基本概念:

1、进程与程序

    程序就是存储在磁盘上的可执行文件,程序被加载到内存中开始运行叫进程。一个程序可以被多次加载生成多个进程,进程就是处于活动状态的计算机程序。

2、进程的分类

    进程一般分为三种类型:交互进程、批处理进程、守护进程。
    守护进程一般都处于活跃状态,运行在后台,由于系统在开机时通过启动脚本自动创建的。

3、查看进程

    简单形式:ps 显示当前用户有控制终端的进程信息。
    列表形式:ps auxw 显示进程详细信息
        a 所有用户的有控制终端的进程
        x 无终端控制的进程
        u 显示进程的详细信息
        w 以更大列宽显示
        USER 进程的属主
        PID 进程的编号
        %CPU CPU使用率
        %MEM 内核使用率
        VSZ 虚拟内存使用的字节数
        RSS 物理内存使用的字节数
        TTY 终端设备号,?表示无终端控制
        STAT 进程的状态
            O 就绪,等待被调度
            R 运行,Linux系统没有O,就绪也用R表示
            S 可被唤醒的睡眠,如系统中断、获得资源、收到信号都可以唤醒它转入运行状态。
            D 不可被唤醒的睡眠,只能被系统唤醒。
            T 暂停状态,收到SIGSTOP信号进程暂停状态,收到SIGCONT信号转入运行状态。
            W 等待内存分页(2.6内核以后被废弃)
            X 死亡状态
            Z 僵尸状态
            < 高优级
            N 低优先级
            l 多线程的进程
            s 会话首进程
            L 有内存被锁进内存分页
            + 在前台进程级中
        START 进程启动的时间
        TIME 进程运行的时间
        COMMAND 启动进程的命令

4、父进程、子进程、孤儿进程、僵尸进程

    一个进程可以被另一个进程创建,创建者叫父进程,被创建者叫子进程,子进程被父进程启动后在操作系统的调用同时运行。
    当子进程先于父进程结束,子进程会向父进程发送SIGCHLD信号,此时父进程应该去回收子进程的相关资源,如果没有收回子进程就会进入僵尸状态。
    僵尸进程:该进程已经死亡,但它的父进程没有立即回收它的相关资源,该进程就进入僵尸状态。
    孤儿进程:父进程先于进程结束,子进程就变成了孤儿进程,孤儿进程会被孤儿院(init守护进程)领养,init就是孤儿进程的父进程。

5、进程标识符

    每个进程都有一个以非负整数表示的唯一标识,即进程ID/PID。
    进程ID在任意时刻都是唯一的,但可以重用,进程一旦结束它的进程ID就会被回收,过一段时间后再重新分配给其它新创建的进程(延时重用)。
    pid_t getpid(void);
    功能:获取进程ID
    pid_t getppid(void);
    功能:获取父进程ID
    init的进程ID永远是1。

进程相关函数

创建进程:

int system(const char *command);
功能:执行一个可以执行文件,这样就创建一个子进程。
返回值:子进程结束后才返回。
该函数的实现调用了fork和waitpid函数,其实是当进程创建一个子进程,子进程又加载了command可执行文件。

pid_t fork(void);

返回值:一次调用两次返回,子进程返回0,父进程返回子进程ID,当进程的数量超过系统的限制会创建进程失败,返回-1。
可以根据返回值的不同让父子进程进入不同的分支,执行不同的代码。

该函数调用后父子进程各自独立运行,谁先返回不确定,但可以通过睡眠确定让哪个进程先执行。

通过fork创建的子进程会拷贝父进程的(数据段、bss段、堆、栈、I/O流缓冲区)等数据同,与父进程共享代码段,子进程会继承父进程的信号处理方式。

通过fork创建的子进程可以共享父进程的文件描述符。

pid_t vfork(void);

功能:以加载可以执行文件方式创建子进程。
返回值:子进程返回0,父进程返回子进程的PID。

子进程先返回,此时子进程并没有创建成功,需要加载一个可以执行文件来替换当前子进程的所有资源,替换完成子进程才算创建成功,此时父进程才返回。

使用exec系列函数加载可执行文件:

int execl(const char *path, const char *arg, ...);
path:可执行文件的路径,
arg:命令行参数,一般每个是可执行文件的名字,至少一个,NULL结尾。

int execlp(const char *file, const char *arg, ...);
file:可执行文件名字,会根据PATH环境变量查找可执行文件;
arg:命令行参数

int execle(const char *path, const char *arg, ..., char * const envp[]);
path:可执行文件的路径
arg:命令行参数
envp:环境变量表,父进程可以在加载子进程时把环境变量传递给子进程,这样父子进程共用一个环境变量表。

int execv(const char *path, char *const argv[]);
path:可执行文件的路径
argv:指针数组,由传递给子进程的字符串组成,以NULL结尾

int execvp(const char *file, char *const argv[]);
file:可执行文件名字,会根据PATH环境变量的查找可执行文件。
argv:指针数组

int execvpe(const char *file, char *const argv[],char *const envp[]);
file:可执行文件名字
argv:指针数组
envp:环境变量表

exec系列函数正常是不会返回会,当加载子可执行文件失败时返回-1。
以excl系列函数创建出的子进程不会继承父进程的信号处理函数,但能继承父进程的信号屏蔽。

进程的正常退出:

1、在main函数中执行 return n,该返回值可以被父进程接收到,它与exit几乎等价。
2、进程调用了exit函数,该函数是标准库函数:
    void exit(int status);
    功能:在任何时候调用此函数都可以结束进程。
    status:结束状态码(EXIT_SUCCESS/EXIT_FAILURE),与main函数中return的返回值效果一样,
    返回值:该函数不会返回

    进程退出前要完成:
        int atexit(void (*function)(void));
        功能:注册一个进程结束时执行的函数
        int on_exit(void (*function)(int , void *), void *arg);
        功能:注册一个进程结束时执行的函数
            int: return 的值或exit函数的参数
            arg:会在进行结束时自动传递给function函数。
        1、先调用事先通过at_exit/on_exit注册过的函数,如果都注册了执行顺序与注册顺序相反。
        2、冲刷并关闭所有打开状态的标准IO流。
        3、该函数的实现调用了_Exit/_exit。
3、调用_exit/_Exit函数
    void _exit(int status);
    功能:结束进程,由系统提供
    void _Exit(int status);
    功能:结束进程,由标准库提供
    1、它们的参数会被父进程获取到。
    2、进程结束前会关闭所有处理打开状态的文件描述符。
    3、会向父进程发送SIGCHLD.
    4、该函数不会返回。
4、进程的最后一个线程执行的返回语句。
5、进程的最后一个结束调用pthread_exit函数。

进程的异常终止:

1、进程调用了abort函数,产生了SIGABRT信号(自杀)。
2、进程接收到了某些信号,可以是其它进程发送的,也可能自己的错误操作造成的(他杀,作死)。
3、进程的最一个线程收到了"取消"操作,并作出了响应。
这三种结束方式父进程无法猎取结束状态码,所以叫异常终止。

注意:不管进程是如何结束的它们都会执行同一段代码,关闭所有打开的文件描述符,释放所有的内存。

子进程回收:

对于任何结束方式,都希望父进程能够知道,通过wait、waitpid函数可以知道子进程是如何结束的以及结束状态码。

pid_t wait(int *status);

功能:等待子进程结束,并获取结束状态。
返回值:子进程的ID
1、如果所有子进程都在运行,则阻塞。
2、如果有一个子进程结束,立即返回该进程结束状态和PID。
3、如果没有子进程则返回-1。

WIFEXITED(status) 判断进程是否是正常结束,如果是则返回真。
WEXITSTATUS(status) 如果进程是正常结束的,可以获取到正确的结束状态码,只获取低8位。
WIFSIGNALED(status) 判断进程是否是异常结束,如果是则返回值。
WTERMSIG(status) 如果进程是异常结束的,可以获取到杀死进程的信号。

注意:由于wait函数可能会阻塞,因此不适合在业务逻辑中调用些函数,可以为SIGCHLD信号注册一个处理函数,在处理函数中调用wait函数。

pid_t waitpid(pid_t pid, int *status, int options);

功能:指定收回某个或某些进程
pid:
    <-1 等待abs(pid) 进程组中的进程结束。
    -1 等待任意子进程结束,功能与wiat等价。
    0  等待同组的任意进程结束。
    >0 等待该进程结束。
status:结束状态,与wiat中的等价。
options:
    WNOHANG 非阻塞模式,如果没有进程结束,立即返回0。
    WUNTRACED 如果有进程处理暂停状态,返回该进程的状态。
    WCONTINUED 如果有进程由暂停转为继续运行,返回该进程的状态。
    
WIFSTOPPED(status) 判断进程是否处理暂停状态,是则返回真。
WSTOPSIG(status) 获取到导致该进程暂停的信号。
WIFCONTINUED(status) 判断该进程是否由暂停转为继续运行,是则返回真。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值