IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 多进程 基础 -> 正文阅读

[系统运维]多进程 基础

多进程:

  1. 什么是进程
    1. 进程是程序在内存中的镜像
    镜像:imag,把程序放在进程中就是进程
    2. 进程是正在运行的程序
    3. CPU 调度的最小单位。
    进程是程序跑起来,调用在内存中,他在进程中构成的对象实例化,叫做进程
    什么是程序 (应用):程序的集合,编译好的,可执行的二进制文件(Linux中为普通文件,不过有x权限:执行权限)

    程序跑起来,调入到内存中,在内存中构建了一个对象或者是一个实例,这个实例叫做进程。
    程序变成进程增加了很多概念:代码,内存空间,用户,组概念,打开的文件,占用的资源,合起来叫做一个进程。
    4. 什么是线程
    
  2. 进程接口有哪些
    1. fork():创建一个子进程
    pid_t fork(void);//pid :process id,返回子进程的id
    调用之后,父进程会拷贝自己一份,然后生成一份孩子进程
    父亲和孩子运行在完全隔离/ 独立的内存空间
    fork的时候内存会有一样的内容,但是内存写,和文件映射,不会产生影响
    但是在fork的时后,有共同的内存空间,这一份数据是唯一的,当内存发生变化(写),拷贝才会真正发生,这个过程叫做写拷贝
    孩子有自己的唯一的process ID
    孩子不会继承父亲的内存锁,因为是两个独立的内存空间
    进程的资源使用量和CPU的使用时间都会重置为0
    孩子不会继承父亲未被执行的信号
    孩子不会继承父亲相关联的记录锁,不会记录父亲的计时器
    不会继承父亲的I/O操作
    总之,子进程不会继承父进程的所有东西,除了父进程在调用子进程时,已经创建的空间。
    返回值:
    父进程返回的是孩子的pid, 孩子返回的是0,孩子可以调用getppid 获得父亲的pid, 也可以通过调用getpid获得自己的pid,
    父进程没有办法获得自己生成进程的pid,除了第一次调用fork 时候的返回值。

#include "head.h"

int main() {
    pid_t pid;
    if ((pid = fork()) < 0) {//fork 出错
        perror("fork()");
        exit(1);
    }
    if (pid == 0) {
        printf("Child Process!\n");
    } else {
        printf("Parent Process\n");
    }
    return 0;
}

输出结果为
Parent Process!
但是一定先输出父进程么?或者说Parent进程一定先执行么?
未必,没有定论,系统会自动调动进程,不过极大概率都是父进程执行
同一时刻只有一个进程在CPU上跑,每个进程占用的时间是一定的,父进程生了孩子,还没用完,所以接着使用,子进程会等待父进程结束,所以大概率父进程先执行,如果父进程生了孩子,时间刚好用完,那么谁先执行就不一定了,
在pid = fork(),时候,生成孩子,孩子进程从该行代码之后执行

计算机中,父进程生孩子之后,让子进程执行任务,然后负责管理子进程

  1. wait() :
    pid_t wait(int *wstatus);//等待状态发生变化,孩子发生状态改变时,会改变状态
    wstatus 0,孩子正常死了,1,孩子出问题死了。。 wstatus 记录孩子的状态
    释放孩子内存的不是父亲,而是父亲等待系统去释放,如果孩子死了,父进程不负责给孩子收尸,不等待,子进程变成僵尸进程,不占CPU,但是占系统资源,可以在top中看到
    上述代码中的总父进程是zsh
    如果孩子改变状态,调用立刻返回,否则,会阻碍程序的进行
    创建僵尸进程
#include "head.h"

int main() {
    pid_t pid;
    if ((pid = fork()) < 0) {//fork 出错
        perror("fork()");
        exit(1);
    }
    int i = 0;
    if (pid == 0) {
        printf("Child Process! is : %d and Parent Process id is %d\n", getpid(), getppid());
    } else {
        printf("Parent Process id is %d\n", getpid());
        while (1) sleep(100);//不可以直接while(1), 会大量占用CPU
    }
    return 0;
}

在这里插入图片描述
ps -aux 查看
kill + 进程杀进程
杀死父进程,子进程也会直接被杀死。
单独kill 子进程无法杀死。

#include "head.h"

int main() {
    pid_t pid;
    int statu;
    if ((pid = fork()) < 0) {
        perror("fork()");
        exit(1);
    } else if (pid == 0) {
        sleep(5);
        printf("Hey I am the child\n");
        return 0;
    } else {
        wait(&statu);
        printf("The child is over and return %d\n", statu);
    }
    return 0;
}

在这里插入图片描述

生10个孩子,并排名

#include "head.h"

int main() {
    pid_t pid;
    pid_t child_pid[15] = { 0 };
    pid_t father = getppid();
    printf("father : %d\n", father);
    int i;
    for (i = 1; i <= 10; i++) {
        if ((pid = fork()) < 0) {
            perror("fork()");
            exit(1);
        }
        if (pid == 0) {
            printf("I am a child and rank the %2d and My pid is %d\n", i, getpid());
            sleep(5);
            printf("I am the %2d th child\n", i);
            return 0;
        }
    }
    sleep(10);
    printf("Over\n");
    /*演示代码*/
    /*pid_t pid;
    int i;
    for (int i = 0; i <= 10; i++) {
        if ((pid = fork()) < 0) {
            perror("fork()");
            exit(1);
        }
        if (pid == 0) break;
    }
    printf("我是第 %d 个孩子!\n", i);
    sleep(100);*/
    return 0;
}

在这里插入图片描述
3. exec() :执行一个新的进程
新进程有不受父进程所管辖的全新进程
#include <unistd.h>
extern char **environ; // 环境变量,一般写函数,都不会使用环境变量
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg ..., /* (char *) NULL */);
int execle(const char *path, const char *arg, .../* (char *) NULL , char *envp[] */);

l : list, 有arg。。。。, 以一个空指针结束
p:从path路径找文件
v: 提供了一个数组,指向了一个以0结尾的字符串
e: 指定一个环境变量,通过envp 传入

不带p ,引入的必须是一个完整的路径,p模拟从shell 里面寻找

exec 家族函数,用一个新的进程映像,替换当前进程映像。
第一个参数,对于函数来说,是将要被执行文件的名字
*arg : 所有在execl(), execlp(), execle()函数中的arg 可以被认为arg0, arg1, arg2…argn

#include "head.h"


int main() {
    pid_t pid;
    if ((pid = fork()) < 0) {
        perror("fork()");
        exit(1);
    }
    if (pid == 0) {
        execlp("vim", "vim", "4.exec.c", NULL);
        printf("In End\n");
    } else {

        wait(NULL);//不关注返回什么
    }



    return 0;
}

execlp代码之后所有的在子进程中均不执行,因为子进程替换成vim 4.exec.c

##Problem

#include "head.h"


int main() {
    pid_t pid;
    if ((pid = fork()) < 0) {
        perror("fork()");
        exit(1);
    }
    int status;
    if (pid == 0) {
        printf("Child Process\n");
        return 1;
    } else {
        wait(&status);
        printf("Child is over, ret = %d\n", status);
    }
    return 0;
}

这段代码中,子进程返回值是1,但是在最后输出的时候,返回的值是256
在这里插入图片描述
为什么?
在这里插入图片描述
最低8位,在小端机中,二进制码为10000000 所以为256.

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-01 17:15:45  更:2021-10-01 17:17:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 17:22:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码