C/C++进程线程超详细详解

news2024/11/25 13:29:05

目录

前言

一、进程基础

1.进程概念

2.进程特征

3.进程状态(如图清晰可见)

4,进程的标识

实例代码如下:

5.进程的种类

实例shell脚本程序如下:

二、进程API

1.创建子进程

实例代码如下:

2.exec函数族

 函数族讲解图如下所示:

实例代码如下所示: 

3.结束进程

实例代码如下所示:

4.给进程收尸(释放进程占用的资源)

 wait实例代码如下:

waitpid实例代码如下: 

总结


前言

进程和线程的广泛意义是什么?

进程是计算机中运行的程序的实例。它具有独立的内存空间和资源,是操作系统分配和管理资源的基本单位。每个进程都拥有独立的地址空间、全局变量和文件打开等资源,进程之间相互独立。进程之间通常通过进程间通信(IPC)机制进行数据交互。

线程是进程中的一个执行单元。一个进程可以包含多个线程,这些线程共享进程的地址空间和资源,可以同时执行不同的代码路径。线程之间可以通过共享内存进行数据交换,因为它们可以访问相同的全局变量和堆内存。


一、进程基础

1.进程概念

进程是一个独立的可调度的任务
    (1)进程是一个抽象实体。当系统在执行某个程序时,分配和释放的各种资源
    (2)进程是一个程序的一次执行的过程
进程和程序的区别
    程序是静态的,它是一些保存在磁盘上的指令的有序集合,没有任何执行的概念
    进程是一个动态的概念,它是程序执行的过程,包括创建、调度和消亡
    进程是程序执行和资源管理的最小单位

2.进程特征

动态性 ----程序一次运行过程
并发性 ----可以同时运行多个进程
独立性 ----每个进程在各自独立的虚拟内存中运行
异步性 ----多个运行的进程之间相互没有关系

3.进程状态(如图清晰可见)

4,进程的标识

(1)主要的进程标识
    进程号(Process Identity Number,PID)
    父进程号(Parent Process ID,PPID)
    
(2)PID唯一地标识一个进程。可以通过以下两个函数获得:
    pid_t getpid(void)     //获取进程ID
    pit_t getppid(void)    //获取父进程ID

实例代码如下:

int main(void)
    {
        printf("pid = %d\n",getpid());
        printf("ppid = %d\n",getppid());
        return 0;
    }

 在终端运行的结果以及ps命令作用结果如下:

5.进程的种类

(1)交互进程:
    该类进程是由shell控制和运行的。交互进程既可以在前台运行,也可以在后台运行。
    
(2)批处理进程:
    该类进程不属于某个终端,它被提交到一个队列中以便顺序执行。

实例shell脚本程序如下:

        终端输入命令如下:

        touch test.sh
        chmod a+x test.sh  
        test.sh内容如下:
        ls
        touch 1.txt 2.txt 3.txt
        ls /
        cat fork1.c

 运行shell脚本文件如下:

     peter@ubuntu:~/2308/proc/day01_code$ ./test.sh
     1.txt  3.txt   exit.c   fork2.c   main.c    myproc.c  test.sh  wait.c   waitpid.c
     2.txt  exec.c  fork1.c  getpid.c  Makefile  test.c    wait     waitpid
     bin   cdrom  etc   initrd.img      lib    lost+found  mnt  proc  run   snap  swapfile  tftpboot         u  sr  vmlinuz
     boot  dev    home  initrd.img.old  lib64  media       opt  root  sbin  srv   sys       tmp                 var    vmlinuz.old
     #include <stdio.h>
     #include <sys/types.h>
     #include <unistd.h>

     int main(void)
     {
         fork();
         printf("hello world\n");
         return 0;
      }

 (3)守护进程:
          该类进程在后台运行。它一般在Linux启动时开始执行,系统关闭时才结束

二、进程API

1.创建子进程

pid_t fork(void);

fork调用过程:
    1,映射新的进程虚拟空间,该进程称为子进程。
    2,将父进程的各个数据段中的数据拷贝到子进程中
    3,父子进程共享代码段
    4,fork()调用过程返回两个值:
                  第一个值:给父进程返回子进程的ID号
                  第二个值:给子进程返回0
           调用失败返回:-1
    5,父子进程,从fork()调用的下一条语句同时运行   

实例代码如下:

void fun(void)
    {
        int i;
        for(i = 0 ; i  < 7; i++){
            printf("我是子进程,我要好好学习\n");
            sleep(1);
        }
    }

    int main(void)
    {
        int i;
        pid_t pid;

        if((pid = fork()) < 0){
            perror("fork");
            exit(1);
        }else if(!pid)
            fun();
        else
            for(i = 0 ; i  < 7; i++){
                printf("我是父进程,我要努力赚钱\n");
                sleep(1);
            }
        return 0;
    }

2.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 * const envp[] */);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);

 函数族讲解图如下所示:

 

实例代码如下所示: 

int main(void)
{
    int i;
    pid_t pid;

    if((pid = fork()) < 0){
        perror("fork");
        exit(1);
    }else if(!pid){   //子进程:执行另一个程序,如:ls
#if 0
        //execl("/bin/ls","ls","-l",NULL);
        //execlp("ls","ls","-l",NULL);
        char * arg[] = {"ls","-l",NULL};
        //execv("/bin/ls",arg);
        execvp("ls",arg);
#else
        //execl("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL);
        char * env[] = {"name = peter","passwd = 123",NULL};
        //execle("/home/peter/2308/proc/day01_code/myproc","./myproc",NULL,env);
        char * arg[] = {"./myproc",NULL};
        execve("/home/peter/2308/proc/day01_code/myproc",arg,env);
#endif
    }else{   //父进程循环打印
        for(i = 0 ; ; i++){
            printf("我是父进程,我要努力赚钱\n");
            sleep(1);
        }
    }
    return 0;
}

3.结束进程

实例代码如下所示:

#include <stdlib.h>
void exit(int status);   //在结束进程之前,会先刷新缓冲,释放缓冲区,关闭打开的文件,然后再结束进程。

 #include <unistd.h>
 void _exit(int status);   //直接结束进程,不会刷新缓冲,释放缓冲区,关闭打开的文件
 //参数 ---status:  0-表示正常结束,非0-表示异常结束
 
 例如: 
 int main(void)
    {
        printf("hello world");

        //exit(1);     
        _exit(1);

        while(1);  
        return 0;     //在main函数中,执行return语句,return会调用exit()
    }

4.给进程收尸(释放进程占用的资源)

(1)wait
    #include <sys/types.h>
    #include <sys/wait.h>
    //作用:给任意一个子进程收尸
     如果子进程没有结束,则父进程会阻塞,直到子进程结束为止。
     如果父进程没有子进程,则wait函数立即返回。               
    pid_t wait(int *wstatus);   
    //参数  ----- 保存子进程结束状态的变量地址
    //返回值 ----成功:收尸的子进程的ID,失败:-1
    

 wait实例代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


int main(void)
{
    int i;
    pid_t pid1,pid2;
    int status;

    if((pid1 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid1){
	for(i = 0 ; i  < 7; i++){
	    printf("子进程1--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(0);
    }
    if((pid2 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid2){
	for(i = 0 ; i  < 3; i++){
	    printf("子进程2--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(120);
    }
    if(wait(&status) < 0){
	perror("wait");
	exit(1);
    }
    printf("给子进程收完尸\n");
    printf("status = %d\n",WEXITSTATUS(status));
    return 0;
}

 (2)waitpid
    //作用:给指定的进程收尸
    pid_t waitpid(pid_t pid, int *wstatus, int options);
    //参数1  ---pid:
                pid > 0   给进程号为pid的子进程收尸
                pid = -1  与wait()相同,给任意子进程收尸
                pid = 0   给与当前进程在同一个进程组的中任意子进程收尸
                pid < -1  给进程组ID为|pid|的进程组中任意子进程收尸
    //参数2 ----保存子进程结束状态的变量地址
    //参数3 ---- 选项,一般为0

waitpid实例代码如下: 

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


int main(void)
{
    int i;
    pid_t pid1,pid2;
    int status;

    if((pid1 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid1){
	for(i = 0 ; i  < 7; i++){
	    printf("子进程1--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(234);
    }
    if((pid2 = fork()) < 0){
	perror("fork");
	exit(1);
    }else if(!pid2){
	for(i = 0 ; i  < 3; i++){
	    printf("子进程2--pid = %d\n",getpid());
	    sleep(1);
	}
	exit(120);
    }
    if(waitpid(pid1,&status,0) < 0){
	perror("wait");
	exit(1);
    }
    printf("给子进程收完尸\n");
    printf("status = %d\n",WEXITSTATUS(status));
    return 0;
}


总结

      本篇文章针对进程线程进行超详细讲解,希望能够帮到大家!

       以后还会给大家展现更多关于嵌入式和C语言的其他重要的基础知识,感谢大家支持懒大王!

       希望这篇博客能给各位朋友们带来帮助,最后懒大王请来过的朋友们留下你们宝贵的三连以及关注,感谢你们!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1043027.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ptmalloc源码分析 - free()函数的实现(10)

目录 一、步骤1-标记MMAP分配的使用munmap_chunk释放 二、步骤2-释放的是小块内存&#xff0c;则chunk放入fastbin 三、步骤3-如果不是MMAP分配&#xff0c;则释放到unsorted bins 四、步骤4-如果nextchunk 就是Top chunk&#xff0c;则直接扩容Top chunk 五、步骤5-如果释…

分享从零开始学习网络设备配置--任务4.1 IPv6地址的基本配置

任务描述 某公司构建了互联互通的办公网&#xff0c;需要不断扩大网络规模。网络管理员小赵决定采用IPv6的地址&#xff0c;满足公司网络规模的未来发展。 由于IPv4地址耗尽及IPv4地址区域分配不均衡&#xff0c;成为运营商必须面临的一个问题。另外随着互联网的商业化&#…

【python】将python脚本打包成可执行的.exe文件 推荐使用auto-py-to-exe

将python脚本打包成可执行的exe文件 1.不推荐使用网上流行的打包程序&#xff0c;主要是有以下几点&#xff0c;一、cx_freeze与Pyinstaller都是命令行的形 式&#xff0c;且对于Pyinstaller的打包常常需要打包完成后&#xff0c;再修改打包后的原路径&#xff0c;二、非可视…

vue wangEditor富文本编辑器 默认显示与自定义工具栏配置

1.vue 显示wangEditor富文本编辑器 <template><div style"border: 1px solid #ccc;"><Toolbar style"border-bottom: 1px solid #ccc" :editor"editor" :defaultConfig"toolbarConfig" :mode"mode"/><…

Vue-diff算法和双向数据绑定原理

Vue–diff算法 我们提到了vue–diff算法之前先说一下关于vue的编译过程 一、Vue的编译过程主要分为以下的几个步骤&#xff1a; 1&#xff0c;解析模板&#xff1a;Vue会将模板解析语法树AST&#xff0c;并且对其中的指令和元素进行标记。 2&#xff0c;优化静态内容&#…

VUE的基本使用——hello,vue

一、准备一个容器root 二、创建一个Vue实例 三、配置容器 四、配置数据 五、将数据渲染到容器中 总结 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthde…

【挑战开发100个项目 | 1. C语言学生管理系统】

本项目是一个简易的学生信息管理系统&#xff0c;用户可以通过命令行界面完成学生信息的增加、删除、修改、查询、排序和列表展示等功能。数据以txt文件形式存储&#xff0c;实现了数据持久化。项目采用模块化设计&#xff0c;具有较好的可读性和扩展性。 一&#xff0c;开发环…

服装租赁小程序商城的作用是什么

如毕业礼服、演出服、场景拍照服、拍戏拍段子等很多人并不会直接全价购买&#xff0c;由于穿着次数少&#xff0c;所以服装租赁在市场中的需求也不少。 但传统线下服装租赁商家也很难拓展到客户&#xff0c;而需求者也无法快速触达到商家&#xff0c;线上经营没有自己的平台&a…

自学WEB后端03-Node.js 语法

学习后端路线&#xff1a; JavaScript 基础语法 Node,js 内置 API 模块 (fs、 path、 http等) 第三方 API 模块 (express、mysql等) 今天主要回顾下Node.js 语法 Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境&#xff0c;它提供了一种能够在服务器端运行 JavaScr…

如何使用php提取文章中的关键词?PHP使用Analysis中英文分词提取关键词

1、下载Analysis&#xff0c;创建test.php测试 2、引入Analysis实现中文分词 <?php include "./Analysis/Analysis.php";$annew \WordAnalysis\Analysis(); $content"机器学习是一门重要的技术&#xff0c;可以用于数据分析和模式识别。"; //10分词数…

Python3操作MySQL8.XX创建表|CRUD基本操作

Python3操作MySQL8.XX创建表|CRUD基本操作 Python3操作SQLite3创建表主键自增长|CRUD基本操作 一&#xff1a; Python3操作Mysql数据库建表 import pymysqlPython3操作Mysql创建表&#xff1a; # 打开数据库连接 db pymysql.connect(host"localhost", user"您…

R语言绘制环状柱状堆积图+分组+显著性

无叠加、显著性的代码&#xff1a; #设置工作环境 rm(listls()) setwd("D:/Desktop/0000/code-main/条形图")#加载R包 library(ggplot2) # Create Elegant Data Visualisations Using the Grammar of Graphics library(tidyverse) # Easily Install and Load the Ti…

联邦学习应用研究现状及发展趋势

本文章主要参考第32届国际人工智能联合会议&#xff08;IJCAI&#xff09;上由清华大学人工智能研究院知识工程研究中心&#xff08;KEG&#xff09;、北京智谱华章科技有限公司、开放群岛开源社区联合编写的《2023联邦学习全球研究与应用趋势报告》&#xff0c;对重点内容进行…

机器学习算法基础--K-means应用实战--图像分割

目录 1.项目内容介绍 2.项目关键代码 3.项目效果展示 1.项目内容介绍 本项目是将一张图片进行k-means分类&#xff0c;根据色彩k进行分类&#xff0c;最后比较和原图的效果。 题目还是比较简单的&#xff0c;我们只要通过k-means聚类&#xff0c;一类就是一种色彩得出聚类之…

一创聚宽的实盘就要关闭了,有没有好用的实盘平台推荐

挺多的&#xff0c;比较普遍的是QMT和Ptrade&#xff0c;python语言&#xff0c;易上手&#xff0c;通用性好&#xff0c;要说适用性可以考虑Ptrade&#xff0c;问一下你的客户经理有没有&#xff0c;用Ptrade的券商也多&#xff0c;如果之前用一创聚宽你可以无缝切换&#xff…

网络安全内网渗透之DNS隧道实验--dnscat2直连模式

目录 一、DNS隧道攻击原理 二、DNS隧道工具 &#xff08;一&#xff09;安装dnscat2服务端 &#xff08;二&#xff09;启动服务器端 &#xff08;三&#xff09;在目标机器上安装客户端 &#xff08;四&#xff09;反弹shell 一、DNS隧道攻击原理 在进行DNS查询时&#x…

python中使用matplotlib绘图

一、背景 当我们在写python程序时&#xff0c;不可避免的需要将数据可视化&#xff0c;也就是绘制出数据的曲线图&#xff0c;以便我们更直观的观察数据间的变化&#xff0c;以及方便对比。此时就要用到matplotlib库了。 matplotlib官方给出的定义是&#xff1a; 翻译过来也就…

SQLAlchemy关联表删除策略设置

目录 SQLAlchemy关联表 常用的级联选项 外键 SQLAlchemy关联表 SQLAlchemy 是一个 Python 的 ORM&#xff08;对象关系映射&#xff09;库&#xff0c;它允许你在 Python 中使用类来表示数据库中的表&#xff0c;从而更方便地进行数据库操作。在 SQLAlchemy 中&#xff0c;可…

ElementUI - 主页面--动态树右侧内容管理

一.左侧动态树 1.定义组件 ①样式&数据处理 <template><el-menu class"el-menu-vertical-demo" background-color"#334157"text-color"#fff" active-text-color"#ffd04b" :collapse"collapsed" router :def…

手撸RPC【gw-rpc】

文章目录 基于 Netty 的简易版 RPC需求分析简易RPC框架的整体实现协议模块 &#x1f4d6;自定义协议 &#x1f195;序列化方式 &#x1f522; 服务工厂 &#x1f3ed;服务调用方 ❓前置知识——动态代理&#x1f573;️Proxy类InvocationHandler 接口 RPC服务代理类内嵌Netty客…