【Linux】系统编程——进程

1.进程相关概念  

1.什么是程序,什么是进程,有什么区别?

2.如何查看系统中有哪些进程?

3.什么是进程标识符?

4.什么叫父进程,什么叫子进程?

5.C程序的存储空间是如何分配?

1.什么是程序,什么是进程,有什么区别? 

        答:程序是静态的概念,gcc xxx.c -o pro磁盘中生成pro文件,叫做程序

        进程是程序的一次运行活动通俗点意思是程序跑起来了,系统中就多了一个进程

2.如何查看系统中有哪些进程?

        答:使用ps指令查看实际工作中,配合grep来查找程序中是否存在某一个进程

                使用top指令查看,类似windows任务管理器

ps-aux|grep int:过滤作用

top指令: 

 

3.什么是进程标识符? 

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

pid = 0;称为交换进程(swapper)

作用——进程调度

pid = 1;init进程

作用——系统初始化

 

 4.什么叫父进程,什么叫子进程?

        答:进程A创建了进程B那么A叫做父进程,B叫做子进程,父子进程是相对的概念,理解为人类中的父子关系

 5.C程序的存储空间是如何分配?

可执行程序包括BSS段、数据段、代码段。

在类UNIX系统下可使用size命令查看可执行文件的段大小信息。如size a.out:

~/Desktop/MyC$ size a.out
   text	   data	    bss	    dec	    hex	filename
   1672	    600	      8	   2280	    8e8	a.out

1.数据段存放已初始化的全局变量和静态变量,数据段属于静态内存分配。
2.BSS段(Block Started by Symbol)存放未初始化的全局变量和静态变量。
        BSS段的数据是可读写的,链接器从可执行文件中得到BSS段的大小,然后申请得到这块内存空间,这块内存空间紧跟在数据段的后面。由此可知BSS段并不占用可执行文件的大小。在使用BSS段之前BSS段会自动初始化为0。所以,未初始的全局变量和静态变量在程序执行之前已经是0了。BSS段属于静态内存分配。

包含数据段和BSS段的整个区段通常称为数据区。

3.代码段:用来存放程序的代码内存空间。它的大小在程序运行前就已经确定了,并且该区域只能读不能写。在代码段中,也有可能包含了一些只读的常数变量,例如字符串常量等。

        代码段和数据段在编译时已经分配了空间,而BSS段则在程序被调入内存后才分配的。因此BSS段(未进行初始化的数据)的内容并不存放在磁盘上的程序文件中。需要存放在程序文件中的只有代码段和数据段(存放已初始化的全局变量和静态变量)的内容。

        程序编译后生成的目标文件至少含有这三个段,这三个段的大致结构图如下所示:

在这里插入图片描述在这里插入图片描述

可执行程序在运行时会多出两个区域:栈区和堆区。
4.栈区:由操作系统自动分配和释放 ,存放函数的参数值,局部变量的值等。每当一个函数被调用时,该函数的返回类型和一些调用的信息也会被存放到栈中。然后这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。栈区是从高地址位向低地址位增长的,是一块连续的内存区域,最大容量是由系统预先定义好的,申请的栈空间超过这个界限时会提示溢出,用户能从栈中获取的空间较小。

小知识:
自动变量:什么是自动变量呢?自动变量就是指在函数内部定义使用的变量。只能在函数内部使用它。自动变量是局部变量,即它的作用区域是在定义它的函数内部。由于自动变量在定义它的函数的外部是不可见的,所以允许我们在这个函数外部或者其他的函数内部定义同名的变量。计算机在执行这个函数的时候,创建这个变量并为它分配内存,当函数执行完毕返回后,自动变量就会被销毁。为自动变量分配内存就是压栈,而函数返回时就退栈。
临时变量是指在未在程序开头部分声明的,待使用它时才声明类型的变量。常见的如函数中定义的变量,循环语句、条件语句中声明定义的变量。这些变量可与主程序中的变量同名,在其作用域里,主程序中的同名变量一般无法调用。并且这种变量有效存在时间是从变量声明开始到相应程序段(循环结构或函数体)结束。

5.堆区:用于动态分配内存,位于BSS和栈中间的地址区域。由程序员亲自用malloc()申请分配和用free()释放。堆是从低地址位向高地址位增长,采用链式存储结构。频繁的 malloc/free造成内存空间的不连续,产生碎片。当申请堆空间时库函数是按照一定的算法搜索可用的足够大的空间。因此堆的效率比栈要低的多。

最后提示一下:内存泄漏是指内存分配出去以后,你再也访问不到了。

2.创建进程函数fork的使用

#include <unistd.h>//头文件
pid_t fork(void);
fork函数调用成功,返回两次
返回值0,代表当前进程是子进程
返回值非负数,代表当前进程为父进程
调用失败,返回-1

3.创建进程函数fork的使用补充

4.进程创建发生了什么事 

5.创建新进程的实际应用场景及fork总结 

fork创建一个子进程的一般目?

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

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

服务器(socket)在收到一个连接请求时创建子进程对接(fork) 

6.vfork创建进程

vfork函数也可以创建进程,与fork有什么区别

关键区别一:

vfork直接使用父进程存储空间,不拷贝。

关键区别二:

vfork保证子进程先运行,当子进程调用exit退出后,父进程才执行。

 

7.进程退出

进程的正常退出:

1.Mian函数调用return

2.进程调用exit(),标准c库

3.进程调用_exit()或者_Exit(),属于系统调用

补充:

1.进程最后一个线程返回 

2.最后一个线程调用pthread_exit

异常退出

1.调用abort

2.当进程收到某些信号时,比如ctrl+C

3.最后一个线程对取消(cancellation)请求做出响应

 推荐使用exit();退出

8.父进程等待子进程退出(一)

为啥要等待子进程退出

创建子进程的目的(前面项目接收到请求创建子进程)——>干活(收集退出状态)

干活——>1.干完没(正常退出:5种)        2.没完(异常退出:3种)

根据退出码判断是否工作完成

  

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

非空:

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

空:

不关心退出状态 

  

父进程等待子进程退出

并收集子进程的退出状态

1.子进程退出状态不被收集,变成僵死进程(僵尸进程)

例如子进程执行3次后执行父进程这时候子进程就是僵尸进程

wait();如下代码中父进程加入了wait();就会等待子进程3次结束后再运行父进程从而不变成僵尸进程

9. 父进程等待子进程退出(二)

 wait和waitpid区别:

wait使调用者阻塞,waitpid有一个选项,可以使调用者不阻塞

孤儿进程?

 父进程如果不等待子进程退出,在子进程之前结束了自己的“生命”,此时子进程叫做孤儿进程

Linux避免系统存在过多孤儿进程,init进程收留孤儿进程,变成孤儿进程的父进程

10.exec族函数

exec族函数函数的作用:

我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。

 功能:
  在调用进程内部执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。
函数族:
  exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe
函数原型:

#include <unistd.h>
extern char **environ;

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg,..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

返回值:
  exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
参数说明:
path:可执行文件的路径名字
arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

下面将exac函数归为带l、带p、带v、带e 四类来说明参数特点。

12.system函数

 system()函数的返回值如下:
成功,则返回进程的状态值;
当sh不能执行时,返回127;
失败返回-1;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值