Linux系统编程—进程

一、相关概念

1、进程与程序:程序是一个静态的概念。如gcc xxx.c -o pro ,磁盘中生成的Pro文件,叫做程序。进程就是程序运行起来,系统中就多了一个进程。

2、查看进程的方法

        (1)可以通过ps指令查看:ps -aux (查看所有包括其他使用者的进程)

        (2)可以使用top指令查看。(类似于Windows任务管理器)

3、进程标识符

        每一个进程都有一个非负整数表示的唯一ID,叫做pid,类似身份证。

                (1)pid = 0:成为交换进程,作用为进程调度。

                (2)pid = 1:init进程,作用为系统初始化。

        编程可以调用getpid函数获取自身的进程标识符,getppid获取父进程的进程标识符。

4、父进程与子进程:A进程创建了B进程,则A为父进程B为子进程。

        环境变量(传给子进程的变量,遗传性是本地变量和环境变量的根本区别)只能单向从父进程传给子进程。不管子进程的环境变量如何变化,都不会影响父进程的环境变量。

5、存储空间的分配:对于老版Linux,是全部复制。对于新版Linux,是对不改变值得采用共享,当改变的时候复制。

        (1)正文段:这是由CPU执行的机器指令部分。通常,正文段是可共享的,所以即使是频繁执行的程序(如文本编辑器、c编辑器颌shell等)在存储器中也只需有一个副本,另外,正文段通常是只读的,以防程序由于意外而修改其自身的指令。  

        (2)初始化数据段

        (3)非初始化数据段:通常将此段成为bss段(“block started by symbol”由符号开始的块)

        (4)栈:局部变量、自动变量以及每次函数调用时所保存的信息都存放在此段中,每次调用函数时其返回值以及调用者的环境信息(例如机器寄存器的值)都存放在栈中 。然后,最近被调用的函数在栈上为其自动和临时变量分配空间。通过这种方式使用栈,可以递归调用c函数。

        (5)堆:通常在堆中进行动态存储分配。例如malloc函数。     

二、创建进程

1、fork函数

目的:(1)一个父进程希望复制自己,使父、子进程同时执行不同的代码段。这在网络服务进程中是常见的——父进程等待客户端的服务请求。当请求到达时使用fork函数,使子进程处理此请求。父进程则继续下一个服务请求到达。

        (2)一个进程要执行一个不同的程序。这对shell是常见的情况。在这种情况下,子进程从fork返回后立即调用exec。

 函数:(1)fork函数被调用一次,但是返回两次,并且值在不同的进程中。因为一个进程的子进程可以有多个,所以该函数的返回值在父进程中返回子进程的pid,可以方便我们区分不同的子进程。因为只能有一个父进程,所以在子进程中返回0。同时也可以通过返回值来区分改进程为子进程还是父进程。

        (3)使用该函数之后,子进程是父进程的副本,获得父进程数据空间、堆和栈的副本。注意父子进程不共享这些空间,只共享正文段。

2、vfork函数

        (1)子进程直接使用父进程的内存空间

        (2)由于内存空间不进行拷贝,所以子进程先运行等子进程调用exit函数退出后,父进程才执行。

三、退出进程

1、正常退出:main函数中调用return、exit()、_exit()、_Exit()。(其中后两种属于系统调用)

     异常退出:调用abort、(当进程受到某些信号时,如ctrl+c)、最后一个线程对取消指令做出响应。

        在任意一种情况下,该终止进程的父进程都能用wait或waitpid函数取得其终止状态。

2、exit、_exit的区别

        _exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。(0表示成功,非0表示失败)

        exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是”清理I/O缓冲”。

3、在进程中exit、_exit的使用

        ‘exit()’与‘_exit()’有不少区别在使用‘fork()’,特别是‘vfork()’时变得很突出。

‘        exit()’与‘_exit()’的基本区别在于前一个调用实施与调用库里用户状态结构(user-mode constructs)有关的清除工作(clean-up),而且调用用户自定义的清除程序 (自定义清除程序由atexit函数定义,可定义多次,并以倒序执行),相对应,_exit函数只为进程实施内核清除工作。

        在由‘fork()’创建的子进程分支里,正常情况下使用‘exit()’是不正确的,这是 因为使用它会导致标准输入输出(stdio: Standard Input Output)的缓冲区被清空两次,而且临时文件被出乎意料的删除(临时文件由tmpfile函数创建在系统临时目录下,文件名由系统随机生成)。在C++程序中情况会更糟,因为静态目标(static objects)的析构函数(destructors)可以被错误地执行。(还有一些特殊情况,比如守护程序,它们的父进程需要调用‘_exit()’而不是子进程;适用于绝大多数情况的基本规则是,‘exit()’在每一次进入‘main’函数后只调用一次。

四、进程的相关状态及转换

1、R (TASK_RUNNING),可执行状态

2、S (TASK_INTERRUPTIBLE),可中断的睡眠状态

3、D (TASK_UNINTERRUPTIBLE),不可中断的睡眠状态

4、T/t (TASK_STOPPED or TASK_TRACED),暂停状态或跟踪状态

5、Z (TASK_DEAD - EXIT_ZOMBIE),退出状态,进程成为僵尸进程

6、X (TASK_DEAD - EXIT_DEAD),退出状态,进程即将被销毁

五 、等待子进程

注:若子进程的退出状态不被收集,则会变成僵死进程(僵尸进程)。waitpid中的WNOHANG也会使子进程变成僵尸进程。

1、相关函数

        (1)wait函数:如果其所有子进程都还在运行,则阻塞。

                                   如果一个子进程已终止,正等待父进程获取其终止状态,则取得该子进程终止状态立即返回。

                                   如果他没有任何子进程,则立即出错返回。

        (2)waitpid函数:

                参数:status参数: 是一个整型数指针

                                                非空: 子进程退出状态放在它所指向的地址中。

                                                空: 不关心退出状态

                        pid参数:

                         options参数:(其中WNOHANG可以使调用者不阻塞,但是会使结束的子进程为僵尸进程)

2、检查wait和waitpid所返回的终止状态的宏

3、若父进程不等待子进程退出,在子进程退出之前就结束,此时子进程叫做孤儿进程。Linux避免存在过多的孤儿进程,则会使init进程收留孤儿进程,init进程变成孤儿进程的父进程。 

六、exec族函数:linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客_execlp函数

        其中路径只为打开可执行文件,不给文件输送任何参数。

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。

        其中设置的errno可以调用perror函数查看具体错误。如下面程序所示

输出结果为: 

七、system函数:

        linux system函数详解 - 南哥的天下 - 博客园

        该函数实际为execl函数的包装,当system执行完毕后,随即返回原调用的进程。

        此函数的缺点为无法获得调用出的内容,无法进行保存和读取。 

八、popen函数:

        linux下popen的使用心得_libinbin_1014的博客-CSDN博客

        此函数的优点为可以获得指令产生的结果或内容。

        当调用成功是需要使用pclose关闭FILE*

  • 26
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值