LinuxGod.net
Linux大神网——精选每一篇高品质的技术干货
  1. 首页
  2. 开源快讯
  3. 正文

共享一个页表和一块物理内存的区别与联系导航

2023年2月12日 396点热度

本文导航:

内容所占比率

线程概念

40%

线程与进程区别与联系

20%

线程异同点

10%

线程控制(创建,中止,等待)

30%

线程的概念

提到线程,我们先从进程说起。

我们写的程序从硬碟加载到显存开始运行时,进程就形成了。也就是操作系统开始为这个程序创建PCB,分配系统资源,例如分配一块虚拟地址空间,一个页表,一块化学显存。当这个进程内部有多个执行流时,如今我们可以简单理解父进程用vfork()创建了多个子进程时linux下socket编程,这种子进程也须要资源。倘若能分得资源都会只身分的资源,但若果分不了就共享。共享一块地址空间。共享一个页表和一块化学显存。

为了易于来理解,我画了一张简明图

这里写图片描述

在这张图中,有3个PCB,在原先的认知里,我们称作3个进程。

如今我们须要引入线程的概念。

线程概念

进程到线程

在明晰线程概念后,我们就要站在线程的角度去理解前面那张图了。

图中3个PCB,我们就要把她们称之为3个线程了。由于这是在进程里的3个执行控制流。她们共享一块虚拟地址空间。一块页表,所以这3个线程所见到的化学类存也是一样的。并且她们可以执行各自的任务linux线程和进程的区别,并有自己生命特点。

所以在图中,进程就是创建执行代码,创建PCB,申请资源,分配资源的实体,即整个图。而线程就是这些单个PCB,在线程中称之为TCB。

其实下边这张图有助于来理解。

线程特征

其中最重要的数据是栈和寄存器。私有栈是为了保存临时变量linux线程和进程的区别,以便函数调用等操作。私有寄存器是为了便捷线程切换,保存上下文。

进程的多个线程共享

.同地址空间,因而TestSegment,DataSegment都是共享的,假如定义个函数雇各线程中都可以调用,假如定义一个全局变量,在各线程中都可以访问到,除此之外,各线程还共享以下进程资源和环境:

进程与线程联系

在Linux下并没有专门为线程设计如此一个概念,也就是说没有真正意义上的线程,它在linux下是由进程模拟的,可以觉得所有的PCB都可以称为轻量级进程(不一定是进程,也可能是线程)。进程是分配系统资源的一个实体linux端口映射,而线程是CPU调度的基本单位。

在单个程序中同时运行多个线程完成不同的工作,称为多线程。相对来说,多进程相对稳定,多线程相对不稳定。可以觉得,进程是分配系统资源的一个实体,而线程是CPU调度的基本单位。

进程具有独立的地址空间,而线程并没有,同一进程内部的线程共享进程的地址空间。

因为Linx下没有真正的线程,Linux用进程来描述线程和组织线程。所以在Linux下只有轻量级的线程,操作系统是看不到线程的TCB的。所以右图中的第四个图:多个进程多个线程图中,操作系统可以看见的是6个PCB,

线程的优点线程的缺点线程控制POSIX线程库

与线程有关的函数构成了一个完整的系列,绝⼤大多数函数的名子都是以“pthread_”打头的

要使用这种函数库,要通过引入头文件,链接这种线程函数库时要使用编译器命令的“-lpthread”选项

常见操作如下

这里写图片描述

创建线程

调用函数

返回值:成功返回0,失败返回错误码

linux 查看进程线程_linux线程和进程的区别_linux 进程 线程

错误检测:

传统的一些函数是,成功返回0,失败返回-1,但是对全局变量errno形参以指示错误。

pthreads函数出错时不会设置全局变量errno(而大部份其他POSIX函数会这样做)。而是将错误代码通过返回值返回pthreads同样也提供了线程内的errno变量,以支持其它使用errno的代码。对于pthreads函数的错误,建议通过返回值业判断,由于读取返回值要比读取线程内的errno变量的开支更小

测试用例

注意:编译链接时,一定要加上-lpthreead选项,见图中命令部份。由于这是用户级别的库,并不是系统提供的库。

#include 
#include 
#include 
//新线程的例程(执行任务,打印字符串)
void * my_run(  void *arg)
{
      while(1)
      {
            printf(  "  i am %sn",(  char *)arg);
            sleep( 1);
      }
}
int main(  )
{
      //申明一个本地变量tid,用来保存对等线程的ID
      pthread_t tid;
      //调用pthread_create函数创建一个新的线程,
      pthread_create(&tid,NULL,my_run,"newthread");
      //调用结束,同时运行,并且tid包含了新线程的id
      while(1)
      {
            printf(  "  i am main threadn");
            sleep(2);
      }
      return 0;
}

pthread_create创建成功!

主线程和新线程各自复印不同的内容。

正常情况下,一个程序里是不会同时执行两个死循环的。并且,在这个程序里,竟然可以同时执行两个死循环。缘由就在于这时两个线程在运行。各自执行不同的任务,有自己的栈空间和寄存器,支持上下文切换和函数调用。

中止线程

假如须要只中止某个线程而不中止整个进程,可以有以下方式:

void * my_run(  void *arg)
{
      while(1)

linux 查看进程线程_linux 进程 线程_linux线程和进程的区别

{ printf( " i am %sn",( char *)arg); sleep( 1); return NULL; } }

新线程中止,主线程继续执行。

-线程可以调用pthread_exit中止自己。

pthreadexit函数

功能:线程中止

 #include 
 void pthread_exit(void *retval);

参数

valueptr:valueptr不要指向一个局部变量。

返回值:无返回值,跟进程一样,线程结束的时侯难以返回到它的调用者(自身)

#include 
#include 
#include 
#include 
void * my_run(  void *arg)
{
      printf("thread 1 returning ....n");
      int *p=(int *)malloc(sizeof(int));
      *p=1;
      pthread_exit((void *)p);
}
int main(  )
{
      pthread_t tid;
      void *ret;
      //thread 1 exit
      pthread_create(&tid,NULL,my_run,NULL);
      //等待新线程退出,退出码保存在ret中
      pthread_join(tid,&ret);
      printf("thread  return,id is:%ld,return code:%dn",tid,*(int *)ret);

linux线程和进程的区别_linux 查看进程线程_linux 进程 线程

free(ret); while(1) { printf("i am main threadn"); sleep(2); } return 0; }

,pthreadexit或则return返回的表针所指向的显存单元必须是全局的或则是用malloc分配的,不能在线程函数的栈上分配,由于当其它线程得到这个返回表针时线程函数早已退出了。

调用phread_exit(),他会等待所有其他对等线程(就是同一个进程中的除自身外其他线程)中止,之后再中止主线程和整个进程。

假如某个对等线程调用linux的exit函数,则该函数中止进程以及所有与该进程相关的线程

pthread_cancel函数

功能:取消一个执行中的线程

#include 
int pthread_cancel(pthread_t thread);

参数

thread:线程ID

返回值:成功返回0;失败返回错误码

void* my_run_2(void* arg)
{
      while(1)
      {
            printf(  "thread 2 is running...n");
            sleep(1);
      }
      return NULL;
}
int main(  )
{
      pthread_t tid;
      void *ret;
      pthread_create(&tid,NULL,my_run_2,NULL);
      sleep(1);
      //取消执行中的线程2
      pthread_cancel(tid);
      //等待线程2的返回状况,获取返回值
      pthread_join(tid,&ret);
      if(ret==PTHREAD_CANCELED)

linux 进程 线程_linux线程和进程的区别_linux 查看进程线程

{ printf("thread return,id is:%ld,return code:PTHREAD_CANCELEDn",tid); } else { printf("thread return,id is:%ld,return code:NULLn",tid); } return 0; }

介绍一个获取当前线程id的函数

 #include 
 pthread_t pthread_self(void);

获取当前文件中线程tid命令

ps -eLf | head -1&& ps -eLf | grep a.out 

以上都是显示中止,另外还有隐式中止。即:顶楼的线程调用返回时,线程会隐式中止。

线程等待

为何须要线程等待?

早已退出的线程,其空间没有被释放,一直在进程的地址空间内。创建新的线程不会复⽤用刚刚退出线程的地址空间。

功能:等待线程结束原型

intpthread_join(pthread_tthread,void**valueptr);

参数

thread:线程ID

value_ptr:它指向一个表针,前者指向线程的返回值返回值:成功返回0;失败返回错误码

调用该函数的线程将挂起等待,直至id为thread的线程中止。thread线程以不同的方式中止,通过pthread_join得到的中止状态是不同的,总结如下:

假如thread线程通过return返回,valueptr所指向的单元⾥里储存的是thread线程函数的返回值。

假如thread线程被别的线程调⽤用pthreadcancel异常终掉,value_ptr所指向的单元里储存的是常数

PTHREADCANCELED。

假如thread线程是自调用pthreadexit中止的,valueptr所指向的单元储存的是传给pthread_exit的参数。

假如对thread线程的中止状态不感兴趣,可以传NULL给value_ptr参数。

测试用例可以参考前面的代码。

线程分离

线程分离插口

#include 
int pthread_detach(pthread_t thread);

#include 
int pthread_detach(pthread_t self());

返回值:都是成功返回0,失败返回-1.

线程被分离后,就不能在进行pthread_join()操作。否则会出错。由于分离后的线程资源手动就被回收了,再进行等待回收资源。必将造成等待失败。

测试用例如下

#include 
#include 
#include  
#include 
void * thread_run(  void *arg)
{
      //新分离线程自我分离
      pthread_detach(pthread_self( ));
      printf("%sn",(  char *)arg);
      return NULL;
}
int  main(  )
{
      pthread_t tid;
      if(  pthread_create(&tid,NULL,thread_run,"thread1 run...")!=0)
      {
            printf("create thread errorn");
            return 1;
      }
      //主线程分离新线程
      //pthread_detach(tid);
      int ret=0;
      sleep(1);
      if(  pthread_join(  tid,NULL)==0)
      {
            printf("wait thread successn");
            ret=0;
      }
      else
      {
            printf("wait thread failedn");
            ret= 1;
      }
      return ret;
}

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: pthread 函数调用 返回值 进程控制块 页表
最后更新:2023年2月12日

Linux大神网

每日更新,欢迎收藏♥ 不积跬步无以至千里,加油,共勉。

点赞
< 上一篇
下一篇 >

Linux大神网

每日更新,欢迎收藏♥
不积跬步无以至千里,加油,共勉。

最新 热点 随机
最新 热点 随机
VMware过期Linux系统CentOS7下载安装1.77下载地址 红旗linux操作系统v11.0-红旗操作系统操作系统吗? 5yw红软基地驱动完美支持windows、mac、linux系统 轻松安装ZeroMQ:Ubuntu系统必备的解决方案 怎么在Win7系统虚拟机上安装LinuxUbuntu的技巧?在这里 Linux必备!安装RAR解压器,轻松解压文件! 虚拟机linux系统下载 什么是linuxLinux(/托瓦兹)的Linux内核 文件永久删除还能找回来吗?关于Win和Mac系统的恢复方法 Ubuntu16.04怎样安装系统更新和应用更新16.04 网卡 centos 启动 Linux选择选择时各企业所参考的依据:以下内容和Centos Linux内核内存检测工具系列中的一篇,配置以及典型应用 虚拟机安装Ubuntu操作系统-Ubuntu空间20G镜像下载 0渗透操作0x02绕过disable_functions插件(组图) 【好玩的网络-第2.5期】分配IP有哪些骚操作?小白保姆级教程 Windows远程连接工具、Ubuntu系统的安装软件及系统 Linux一模一样远程连接编辑的操作图是什么? DRAM中的虚拟地址空间的缓存简化内存管理(组图) 2.5创建和配置虚拟机2.5.1创建虚拟机双击桌面的VMwarePlayer 掌握Linux基础命令-上海怡健医学系统 服务器上安装linux系统的具体操作过程-如何选择系统?
Linux文件路径查询方法,轻松获取文件位置Linux移植6410:从零开始的挑战!linux php安装 快速掌握Linux下PHP安装,轻松入门流行技术linux patch 文件 解决LinuxPatch文件10大疑难杂症,轻松应对!Ubuntu系统更改IP地址的简易教程,跟随以下步骤即可搞定!高效搭建Linux Android开发环境,轻松提升开发体验轻松掌握:如何查询Linux内核版本?Linux安装Matlab指南,快速掌握安装步骤Ubuntu 16安装网卡驱动教程,轻松解决网络连接问题Linux启动时,不使用图形界面可能更有效率!移植Linux,手机变身“大杀器”!详解8大关键操作Linux更高效,掌握启动终端快捷键!纯Python库实现上面介绍的HTML转换为PDF的软件Fedora 13服务器配置指南:9个实用技巧全解析9种方法轻松获取Linux版本,快速掌握系统信息!博客韦东山freeRTOS系列教程:入门文档教程+进阶视频教程轻松掌握linux ldd命令的技巧,成为高效开发者与管理员Linux VPS安全检测,保障服务器稳定运行!Linux下高效开发必备:配置Tomcat和JDK分析Linux中的I2C驱动程序框架核心结构(i2c-bus结构)
Asahi团队将手伸向M2芯片,支持M1Ultra的MacStudio 如何不重新编译整个内核支持某个功能,对系统无影响编译 Linux上架构示意图munin的架构非常简单的配置和客户端插件 Linux在未来服务器领域仍是大势所趋! Linux版本的Interbase4.0,这是一个高性能 Linux游戏起源于最受欢迎的游戏平台:SteamOS介绍 【Linux基础知识】无缓存的反向代理加速,简单的负载均衡和容错.3模块化 【知识点】如何记录常用的linux命令?(二) Ubuntu下安装nvidia显卡驱动获取显卡的型号图 Linux和Unix操作系统之间有区别但也有联系?(一) linux php安装 快速掌握Linux下PHP安装,轻松入门流行技术 LinuxKernel5.7引入了第三种方式:LSM扩展伯克利包过滤器 Linux系统用户系统上的三种类型的帐户的介绍 PS教程:如何用gif文件来形容文件的意思? linux查询端口的方法及使用检查端口查询方法 #java#javac-version有版本输出说明安装成功案例 普联技术有限公司程序的安装包使用方法通过-LINK 精通Linux程序设计的高级程序员并非一件可望不可及的事情 Linux系统下如何定位出CPU使用率过高的进程?(组图) 【报错日志】一下升级linux内核的启动顺序为0
标签聚合
sudo linux系统 linux脚本 软件 电脑 linux服务器 命令 文件目录 虚拟机 命令模式
书籍
课程
技术群
技术干货大合集↓
  • 2023年3月 / 112篇
  • 2023年2月 / 84篇
  • 2023年1月 / 161篇
  • 2022年12月 / 187篇
  • 2022年11月 / 76篇
友情链接:

Linux书籍 | Linux命令 | Linux系统 | RHCE红帽认证 | Linux软件 | Linux教程 | CentOS系统 | Linux内核 | Linux服务器 | Linux大神 | IT资源

COPYRIGHT © 2023 linuxgod.net ALL RIGHTS RESERVED.