进程基础总结

进程概念

正在执行中的程序。

进程终止

有八种方式使进程终止:五种正常返回,三种异常终止。

五种正常返回为:
1. 从main函数返回;
2. 调用exit;
3. 调用_exit或_Exit;
4. 最后一个线程从其启动例程返回;
5. 从最后一个线程调用pthread_exit;
三种异常终止方式为:
6. 调用abort;
7. 接到一个信号;
8. 最后一个线程对取消请求做出相应。

如何创建进程

//三种方式
1. pid_t fork()
2. exec()
3. int system()

fork()函数

fork()函数通过系统调用创建一个与原来进程(父进程)几乎完全相同的进程(子进程是父进程的副本)
eg:
父子进程相同处:全局变量,.data, .text,栈,堆,环境变量,用户ID,宿主目录,进程工作目录,信号处理方式。
父子进程不同之处:进程ID, fork返回值,父进程ID,进程运行时间,闹钟,未决信号集

now:
看起来子进程像是复制了父进程0-3G的虚拟内存空间,以及父进程的PCB,但PID不同,然后映射至物理内存上。实际上fork()做了如下处理“读时共享,写时复制”来节省了内存开销。

pid_t fork();

fork()函数具有两个返回值。其返回值分别为0和大于0的值。

  1. 返回值等于0,其为子进程。
  2. 返回值大于0,其为父进程。

    循环创建N个子进程

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main(void) {
    for(int i = 0; i < n; i++) {
        pid_t pid = fork();
        if(pid == -1) {
            perror("fork err");
            exit(1);
        } else if (pid == 0) {
            printf("i am parent\n");
        } else {
            //出口
            break;
        }
    }
    return 0;
}

exec函数族

#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execv(const char *path, char *const argv[]);
int execvp(const char *file,  char *const argv[]);
int execve(const char *file,
                char *const argv[],
                char *const envp[]);
int execle(const char *path, 
                const char *arg, ...,
                char * const envp[]);
后 缀操作能力
l希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志
v希望接收到一个以NULL结尾的字符串数组的指针
p是一个以NULL结尾的字符串数组指针,函数可以DOS的PATH变量查找子程序文件
e函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境

使用exec函数启动的进程,替换原有的进程,其进程号仍为调用exec函数的进程的进程号。

  1. exec函数需要注意末尾加上作为NULL的结束标志。
  2. 其第一个argv,其为argv[0]。
  3. exec函数执行完后,不再执行该函数后的内容。
  4. exec函数的判断直接使用perror(“exec err”);即可

孤儿进程

父进程死于子进程结束前。子进程的父亲ID即变为init进程的进程号。

僵尸进程

 子进程死亡后父进程没有对子进程进行回收。
 这将导致系统资源的浪费,尤其是再服务器中,长时间不会停止,如果一旦产生僵尸进程,则服务器资源将会被耗尽。
 由于子进程已经死了,使用KILL命令也无法消除掉它。

进程回收

  int wait(int *status);
  //作用:阻塞等待子进程退出、
  //回收子进程残留资源、
  //获取子进程结束状态。  
  //status用来获取状态信息

一个进程在终止时会关闭所有文件描述符,释放在用户空间分配的内存,但它的PCB还保留着,内核在其中保存了一些信息:如果是正常终止则保存着退出状态,如果是异常终止则保存着导致该进程终止的信号是哪个。这个进程的父进程可以调用wait或waitpid获取这些信息,然后彻底清除掉这个进程。
当进程终止时,操作系统隐式回收机制会:1.关闭所有文件描述符 2.释放用户空间分配的内存。内核的PCB仍存在。其中保存进程的退出状态。(PCB位于 /usr/src/linux-haeders-3.16.0-30/include/linux/sched.h)

宏函数作用
WIFEXITED(status)如果结果非0,则进程正常结束
WEXITSTATUS(status)如果WIFEXITED(status)为真,则此宏获取进程退出状态
WIFSIGNALED(status)如果结果非0,则进程异常终止
WTERMSIG(status)如果WIFSIGNALED(status)为真,则此宏获取进程终止信号的编号
 pid_t waitpid(pid_t pid, int *status. int options);
//参数:
 //pid == -1 等待任一子进。
 //pid > 0 等待进程ID与pid相等的进程。
 //pid == 0 等待其组ID等于调用进程组ID的任一子进程。
 //pid < -1 等待其组id等于pid的绝对值的任一子进程。
//返回值:
 // > 0 :返回清理掉的子进程ID
 // - 1 :无子进程
 // = 0 :参数3为WNOHANG,且子进程在运行。

多进程调试

set  follow-fork-mode parent //命令设置GDB在fork后跟踪父进程
                             //不设置默认为父进程
set  follow-fork-mode child  //命令设置GDB在fork后跟踪子进程
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值