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

目录

前言

一、进程基础

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();elsefor(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.mzph.cn/news/90928.shtml

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

相关文章

Socket网络编程练习题四:客户端上传文件(多线程版)

题目 想要服务器不停止&#xff0c;能接收很多客户上传的图片&#xff1f; 解决方案 可以使用循环或者多线程 但是循环不合理&#xff0c;最优解法是&#xff08;循环多线程&#xff09;改写 代码实战 客户端代码 package com.heima;import java.io.*; import java.net.S…

深度学习算法在工业视觉落地的思考

0.废话 距离上次的栈板识别的思考已经过去3个月&#xff0c;中间根据客户的需求和自己的思考&#xff0c;对软件又重新做了调整。但是整体上还是不满意。 0.1 老生常谈的工业视觉落地架构 对于软件架构&#xff0c;我实在没有太多的参考。没办法&#xff0c;公司根本不关心软…

使用华为eNSP组网试验⑵-通过端口地址进行静态路由

有了网络模拟器可以对很多网络应用场景进行模拟&#xff0c;既方便学习又有利于实际的网络实施。 之前因为没有用过&#xff0c;用过了才知道eNSP的好处。但是与思科模拟器不同&#xff0c;连接是自动连接&#xff0c;不能确定端口&#xff0c;比如使用指定的光纤端口或者RJ45的…

CSS详细基础(六)边框样式

本期是CSS基础的最后一篇~ 目录 一.border属性 二.边框属性复合写法 三.CSS修改表格标签 四.内边距属性 五.外边距属性 六.其他杂例 1.盒子元素水平居中 2.清除网页内外元素边距 3.外边距的合并与塌陷 4.padding不会撑大盒子的情况 七.综合案例——新浪导航栏仿真 …

QT按钮介绍

目录 按钮基类 QAbstractButton QPushButton QToolButton QRadioButton QCheckBox 按钮基类 QAbstractButton 这是按钮的基类&#xff0c;它是继承QWidget类 它可对当前的图标&#xff0c;标题等进行设置。 它有自己的一些信号与槽函数&#xff1a; /* 当按钮被激活时(即…

Chrome(谷歌浏览器)如何关闭搜索栏历史记录

目录 问题描述解决方法插件解决&#xff08;亲测有效&#xff09;自带设置解决步骤首先打开 地址 输入&#xff1a;chrome://flags关闭浏览器&#xff0c;重新打开Chrome 发现 已经正常 问题描述 Chrome是大家熟知的浏览器&#xff0c;但是搜索栏的历史记录如何自己一条条的删…

asp.net core mvc 文件上传,下载,预览

//文件上传用到了IformFile接口 1.1文件上传视图 <form action"/stu/upload" method"post" enctype"multipart/form-data"><input type"file" name"img" /><input type"submit" value"上传&…

国庆day1

发送数据 #include<myhead.h>//消息结构体 typedef struct {long msgtype; //消息类型char data[1024]; //消息正文 }Msg_ds;#define SIZE sizeof(Msg_ds)-sizeof(long) //正文大小 int main(int argc, const char *argv[]) {//1、创建key值key_t ke…

Microsoft Office无法重装报错30015-44(3) 0-2031(17004)

1.问题描述 由于迁移文件夹导致Microsoft office软件无法使用&#xff0c;于是准备卸载重装&#xff0c;但是点击OfficeSetup.exe出现报错30015-44(3) 关闭后出现以下报错0-2031(17004) 2. 尝试的解决方式 重启后仍然无法解决问题 2.1 参考官网解决办法 手动从控制面板&…

Spring源码分析(四) Aop全流程

一、Spring AOP基础概念 1、基础概念 连接点(Join point)&#xff1a;能够被拦截的地方&#xff0c;Spring AOP 是基于动态代理的&#xff0c;所以是方法拦截的&#xff0c;每个成员方法都可以称之为连接点&#xff1b;切点(Poincut)&#xff1a;每个方法都可以称之为连接点&…

Sentinel学习——CAP理论,微服务中的雪崩问题,和Hystix的解决方案 Sentinel的相关概念 + 下载运行

前言 Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件&#xff0c;主要以流量为切入点&#xff0c;从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 本篇博客介绍CAP理论&#xff0c;微…

【C++】单例模式

文章目录 一. 介绍二. 饿汉模式三. 懒汉模式四. 饿汉模式和懒汉模式对比 一. 介绍 单例模式是属于设计模式的一种&#xff0c;那什么是设计模式呢&#xff1f; 设计模式&#xff08;Design Pattern&#xff09;是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总…

产品经理如何科学的进行需求调研?

导语&#xff1a;作为产品经理&#xff0c;需求调研是开展工作的重要环节之一。科学、有效地进行需求调研不仅可以帮助产品经理更好地了解用户需求&#xff0c;还能指导产品设计和功能开发&#xff0c;提升产品的竞争力。本文将介绍几种科学的方法和技巧&#xff0c;帮助产品经…

嵌入式MCU都有什么高级用法?

嵌入式MCU都有什么高级用法&#xff1f; 您举的几个例子&#xff0c;确实是MCU外设的一些高端玩法。只是不知道您是否想过&#xff0c;既然这些机制是被 人设计出来的&#xff0c;那它就是种标准用法。从微控制器的发展历程来看&#xff0c;许多硬件机制都是有了实际 需求后才…

nodejs+vue 网上招聘系统elementui

第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;技术背景 5 3.2.2经济可行性 6 3.2.3操作可行性&#xff1a; 6 3.3 项目设计目标与原则 6 3.4系统流程分析 7 3.4.1操作流程 7 3.4.2添加信息流程 8 3.4.3删除信息流程 9 第4章 系统设计 11 …

进阶指针(三)--- qsort函数(快速排序)的使用和(用冒泡排序)模拟实现

✨博客主页&#xff1a;小钱编程成长记 &#x1f388;博客专栏&#xff1a;进阶C语言 &#x1f388;推荐相关博文&#xff1a;进阶C语言&#xff08;一&#xff09;、进阶C语言&#xff08;二&#xff09; 进阶指针&#xff08;三&#xff09; 8.回调函数&#xff08;下&#x…

ThreeJS-3D教学四-光源

three模拟的真实3D环境&#xff0c;一个非常炫酷的功能便是对光源的操控&#xff0c;之前教学一中已经简单的描述了多种光源&#xff0c;这次咱们就详细的讲下一些最常见的光源&#xff1a; AmbientLight 该灯光在全局范围内平等地照亮场景中的所有对象。 该灯光不能用于投射阴…

Windows系统利用cpolar内网穿透搭建Zblog博客网站并实现公网访问内网!

文章目录 1. 前言2. Z-blog网站搭建2.1 XAMPP环境设置2.2 Z-blog安装2.3 Z-blog网页测试2.4 Cpolar安装和注册 3. 本地网页发布3.1. Cpolar云端设置3.2 Cpolar本地设置 4. 公网访问测试5. 结语 1. 前言 想要成为一个合格的技术宅或程序员&#xff0c;自己搭建网站制作网页是绕…

ElementUI之首页导航+左侧菜单->mockjs,总线

mockjs总线 1.mockjs 什么是Mock.js 前后端分离开发开发过程当中&#xff0c;经常会遇到以下几个尴尬的场景&#xff1a; - 老大&#xff0c;接口文档还没输出&#xff0c;我的好多活干不下去啊&#xff01; - 后端小哥&#xff0c;接口写好了没&#xff0c;我要测试啊&#x…

【前端】ECMAScript6从入门到进阶

【前端】ECMAScript6从入门到进阶 1.ES6简介及环境搭建 1.1.ECMAScript 6简介 &#xff08;1&#xff09;ECMAScript 6是什么 ECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在2015年6月正式发布了。它的目标&#xff…