Linux系统编程之进程

1、进程控制块=进程描述符(PCB)

进程状态(4/5种):就绪(初始化),运行,挂起(=等待), 停止
PBC成员:
1、进程id
2、进程状态
3、进程切换需要保存和恢复的CPU寄存器
4、描述虚拟地址空间信息
5、描述控制终端的信息
6、当前工作目录
7、umask掩码
8、文件描述符
9、信号相关的信息
10、用户和用户组id
11、会话(session)和进程组
12、资源使用上限(命令ulimit -a, 查看资源上限值)
这里写图片描述

2、环境变量

2.1 环境变量

环境变量,是指在操作系统中用来指定操作系统运行环境的一些参数。通常具备以下特征:
① 字符串(本质) ② 有统一的格式:名=值[:值] ③ 值用来描述进程环境信息。
2.1、环境变量
在libc库中使用外部名变量:environ获取当前系统全部的系统变量。
这里写图片描述

2.2、获取和设置环境变量

获取环境变量接口名称:

#include <stdlib.h>
/*
param:
    name: 表示环境变量名称
*/
char *getenv(const char *name); 

设置和取消环境变量

#include <stdlib.h>
/*
param:
    name: 环境变量名
    value: 环境变量
    rewrite:0:不覆盖,非0:覆盖
*/
int setenv(const char* name, const char *value, int rewrite);
/*
param:
    name:环境变量名
*/
void unsetenv(const char *name);

例子:

#include <stdio.h>
#include <stdlib.h>
int main()
{
        char *path = getenv("PATH");    //获取环境变量
        printf("PATH:%s\n", path);
        setenv("PATH", "hello", 0);     //0:不覆盖之前,非0:覆盖        
        printf("PATH:%s\n", getenv("PATH"));
        unsetenv("PATH");               //删除环境变量

        return 0;
}

进程控制

这里写图片描述
创建进程:

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

int var = 34;
int main(void)
{
    pid_t pid;
    pid = fork();
    if (pid < 0 ) { //出错
        perror("fork");
        exit(1);
    } else if (pid > 0) {   //父进程
        sleep(2);
        var = 55;
        printf("I'm parent pid = %d, parentID = %d, var = %d\n", getpid(), getppid(), var);
    } else if (pid == 0) {  //子进程
        var = 100;
        printf("child  pid = %d, parentID=%d, var = %d\n", getpid(), getppid(), var);
    }
    printf("var = %d\n", var);

    return 0;
}

4、如何创建N个进程
简单想想写下如下代码:

for(int i = 0; i < N; i++){
    pid_ t pid = fork();
    if(pid > 0){

    }else if(pid == 0){
        //break;
    }else{

    }
}

但这样事实果真如此吗?上述情况创建进程会创建2^N-1个进程,因为在子进程中还会去创建孙进程,如此子子孙孙创建得不是N个进程。避免已创建的子进程也去创建进程,我们应该在else if(pid == 0)上就break来跳出当前的for循环。

5、如何使用GDB调试多线程:

set follow-fork-mode child  //切换子进程
set follow-fork-mode father //gdb下默认进入父进程,切换回子进程

在gdb下上面两个命令实现父进程和子进程的切换

6、防止孤儿进程和僵死进程

子进程都是通过父进程来回收的。如果父进程先退出子进程还在运行,就会产生僵死进程。
僵尸进程是不能用kill 命令清除掉的,因为kill 命令只是用来终止进程的,而僵尸进程已经终止了。
子进程回收函数:

#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int status);
pid_t waitpid(pid_t pid, int *status, int options);

特点:
1. 如果子进程还在运行会阻塞等待。
2. 带子进程的终止信息立即返回。
3. 出错(return -1)立即返回。

区别:

  1. 如果父进程的所有子进程都还在运行,调用wait将使父进程阻塞,而调用waitpid时如果在options参数中指定WNOHANG可以使父进程不阻塞而立即返回0。
  2. wait等待第一个终止的子进程,而waitpid可以通过pid参数指定等待哪一个子进程。

猜你喜欢

转载自blog.csdn.net/hz951290428/article/details/79986741