首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Linux 进程、线程、文件描述符的底层原理

Linux 中的进程其实就是一个数据结构,顺带可以理解文件描述符、重定向、管道命令的底层工作原理,最后我们从操作系统的角度看看为什么说线程和进程基本没有区别。...内核对于一个进程的描述,也可以称为「进程描述符」。...我们常说的「文件描述符」就是指这个文件指针数组的索引,所以程序的文件描述符默认情况下 0 是输入,1 是输出,2 是错误。 我们可以重新画一幅图: ?...到这里,你可能也看出「Linux 中一切皆文件」设计思路的高明了,不管是设备、另一个进程、socket 套接字还是真正的文件,全部都可以读写,统一装进一个简单的files数组,进程通过简单的文件描述符访问相应资源...为什么说 Linux 中线程和进程基本没有区别呢,因为从 Linux 内核的角度来看,并没有把线程和进程区别对待。

2.3K30
您找到你想要的搜索结果了吗?
是的
没有找到

Linux 进程、线程、文件描述符的底层原理

说到进程,恐怕面试中最常见的问题就是线程和进程的关系了,那么先说一下答案:在 Linux 系统中,进程和线程几乎没有区别。...Linux 中的进程其实就是一个数据结构,顺带可以理解文件描述符、重定向、管道命令的底层工作原理,最后我们从操作系统的角度看看为什么说线程和进程基本没有区别。...内核对于一个进程的描述,也可以称为「进程描述符」。...我们常说的「文件描述符」就是指这个文件指针数组的索引,所以程序的文件描述符默认情况下 0 是输入,1 是输出,2 是错误。...为什么说 Linux 中线程和进程基本没有区别呢,因为从 Linux 内核的角度来看,并没有把线程和进程区别对待。

1.3K10

Linux内核13-进程切换

硬件上下文是进程执行上下文的一个子集,进程执行上下文包含进程执行所需要的所有信息。在Linux中,进程的硬件上下文一部分存储在进程描述符中,而其它部分存储在内核态的栈中。...旧版本的linux利用x86架构提供的硬件支持,并通过远程调转指令(GNU-ljump;Intel-jmp far)进行进程切换,跳转到下一个进程的任务状态段(TSS描述符。...1.2 任务状态段-TSS x86架构包含一个特殊的段寄存器,称为任务状态段(TSS),用来保存硬件上下文内容。尽管Linux不使用硬件上下文切换,但还是给每个不同CPU建立一个TSS。...在Linux的设计中,每个CPU就只有一个TSS,所以,Busy位总是设为1。换句话说,Linux中Type域一般为11。...1.3 线程域 每当进程切换时,将要被替换掉的进程硬件上下文内容都应该被保存到某个地址。显然不能保存在TSS中,因为Linux为每个CPU就建立了一个TSS,而不是为每个进程建立TSS

1.8K20

Linux进程描述符task_struct结构体详解--Linux进程的管理与调度(一)【转】

Linux内核通过一个被称为进程描述符的task_struct结构体来管理进程,这个结构体包含了一个进程所需的所有信息。它定义在include/linux/sched.h文件中。...进程内核栈 void *stack; 内核栈与线程描述符 对每个进程Linux内核都把两个不同的数据结构紧凑的存放在一个单独为进程分配的内存区域中; 一个是内核态的进程堆栈 另一个是紧挨着进程描述符的小数据结构...Linux把thread_info(线程描述符)和内核态的线程堆栈存放在一起,这块区域通常是8192K(占两个页框),其实地址必须是8192的整数倍。...线程描述符驻留与这个内存区的开始,而栈顶末端向下增长。 下图摘自ULK3,进程内核栈与进程描述符的关系如下图: ?...内核栈数据结构描述thread_info和thread_union thread_info是体系结构相关的,结构的定义在thread_info.h中 Linux内核中使用一个联合体来表示一个进程的线程描述符和内核栈

2.1K20

LinuxLinux进程的理解 --- 冯诺依曼体系、进程描述符、状态、优先级、切换…

Linux操作系统再通过双向循环链表的数据结构将数量庞大的进程进行组织,这样的话,管理进程就变成了对进程所对应的PCB进行相关的管理。...,我们的进程也可以被当作一个目录,Linux下一切皆文件 ls /proc/进程的pid 三、如果删除掉了进程对应的磁盘上的二进制可执行程序,进程还会运行吗?...通过ps -al指令可以查看到进程的详细信息,PRI和NI的值合并在一起代表Linux进程的优先级。PRI其实就是最终优先级,只不过它受NI值的调控。...4.修改Linux下的优先级(top指令 + root身份) 1. 最终优先级=老的优先级(固定为80)+nice值,Linux支持进程在运行中,通过修改nice值的改变来进行进程优先级的调整。...,还可以开直播和别人聊天,还可以打开xshell进行linux的学习,但这些进程并不是同时在一个CPU下运行的,只是采用了进程切换的方式来完成的。

1.1K20

操作系统进程的实现---中---05

内核–进程的调度schedule和switch_to解析 任务状态段TSSTSS描述符、局部描述符表LDT及LDT描述符 Linux 0.11用tss切换,但也可以 用栈切换,因为tss中的信息可以...当段间指令jmp所含指针的选择符指示一个可用任务状态段的TSS描述符时,将造成任务切换。那么CPU怎么识别描述符TSS描述符而不是其他描述符呢?...这是因为所有描述符(一个描述符是64位)中都有4位用来指示该描述符的类型,如描述符类型值是9或11都表示该描述符TSS描述符。...首先,将当前父进程的eip和cs放在tss中,说明子进程一会如果执行的话,会从父进程在中断进入内核态时,压入栈中的eip和cs处开始执行 然后eax设置为了0,这一点很重要 因为linux 0.11...hello程序了 ---- 小结 Linux 0.11的TSS方式: 对于TSS方式完成内核线程的切换而言,主要通过一条长跳转指令,通过将CPU状态拍到老进程TSS上,而将新进程TSS拍到当前

75760

在winxp环境下,用windbg查看GDT表、IDT表、TSS描述符

一开始什么都不会,不知道如何下手,看ppt上面有个kd>,都不知道kd怎么出来的,自己打开windbg照着网上的选择attach to ……,随便找了个进程打开也不是kd开头的。...网上搜索了一圈,才觉得查看GDT、IDT、TSS这些应该是属于内核调试的。...00000000 IDT: 8003f400 GDT: 8003f000 TSS...但是感觉又有点不相信,接着往下看,第一次看的时候没看懂下面的dd是干什么,后来好像有点懂了,这里dd后面加的是8003f000,这不就是GDT后面的值嘛,应该是它的地址了,那既然查看GDT是这样,那查看IDT、TSS...描述符: lkd>dd 80042000 80042000 0c458b24 b2806de0 8b080010 758b0855 80042010 eac14008 ffe68110 030000ff

1.4K40

linux0.11看一个进程的诞生

这一篇大致说一下进程的创建,有兴趣的可以参考之前的一些文章或者直接上代码https://github.com/theanarkh/read-linux-0.11。 系统有一个GDT表。...该表保存了系统和所有进程tss和ldt描述符信息。tss就是我们平时说的进程上下文。每个进程有一个ldt数组,里面保存了代码段和数据段的描述符信息。 首先,从一个进程的诞生说起。...和ldt地址到gdt,nr << 1即乘以2,这里算出的是第nr个进程距离第一个tss描述符地址的偏移, 单位是8个字节,即选择描述符大小,_LDT是偏移的大小,单位是1,这里是8...挂载tss和ldt地址到gdt,nr << 1即乘以2,这里算出的是第nr个进程距离第一个tss描述符地址的偏移, 单位是8个字节,即选择描述符大小,_LDT是偏移的大小,单位是1,这里是...然后使用tss结构体的内容恢复执行上下文。然后找到tss中的ldt选择子,把ldt选择子加载到ldtr寄存器,然后根据ldt选择子到gdt表中可以找到对应的ldt描述符。根据cs:ip的值。

1.4K11

通过linux0.11源码理解进程的虚拟地址、线性地址、物理地址

在保护模式下,段寄存器保存的是段选择子,当进程被系统选中执行时,会把tss和ldt等信息加载到寄存器中,tss是保存进程上下文的,ldt是保存进程代码和数据段的首地址偏移以及权限等信息的。...和idt地址到gdt,nr << 1即乘以2,这里算出的是第nr个进程距离第一个tss描述符地址的偏移, 单位是8个字节,即选择描述符大小 */ set_tss_desc...接着计算一个在全局描述符GDT中的一个索引,这个索引是ldt选择子。后面会讲到。然后计算进程的代码和数据的线性地址首地址和限长,写到ldt的描述符中。接着复制页表,但是不分配物理地址。...[n])); \ } ljmp tss描述符后,系统会加载第n个进程tss选择子到ltr(保存tss选择子和首地址偏移信息的寄存器),根据选择子从GDT拿到tss的段选择符,然后找到tss的内容,再把某些内容加载到相应寄存器...最后根据tss中的cs和ip执行进程。这就是文章开头的过程。这就是linux0.11版本中进程地址管理的实现。下面是fork后的结构图。 ?

1.4K60

理解进程的新建和执行过程

本文以linux0.11版本为基础,分析进程的内存布局,现代版本已经发生比较大的变化,都是很多原理都是类似的。...每个进程可以定义一个LDT,用于存储代码段和数据段信息。GDT布局如下。 ? GDT每个项(GDT描述符)对应的结构体是 ?...// nr是进程id,计算进程的ldt结构在gdt中的索引,执行该进程的时候,从GDT的第tss->ldt项中取得进程的信息。...和ldt地址到gdt,nr << 1即乘以2,这里算出的是第nr个进程距离第一个tss描述符地址的偏移, 单位是8个字节,即选择描述符大小,_LDT是偏移的大小,单位是1,这里是8 */ set_tss_desc...执行进程的时候,根据进程号,算出tss在gdt的索引,然后把索引里指向的tss里的上下文也加载到对应的寄存器,tss信息中的ldt索引首先从gdt找到进程ldt结构体数据的首地址,即desc_struct

71020

进程实现原理

init()函数中,便是用来调用linux的shell脚本程序,从而可以与用户进行交互。那么问题来了,fork是如何做到进程的创建的呢?系统如何让两个进程或多个进程并发的执行呢?...to the system call movl $0x10,%edx # set up ds,es to kernel space mov %dx,%ds # ds,es 指向内核数据段(全局描述符表中数据段描述符...mov %dx,%es movl $0x17,%edx # fs points to local data space mov %dx,%fs # fs 指向局部数据段(局部描述符表中数据段描述符...tss描述符传给临时变量转给tmp.a,即给cpu寄存器拍了个照,留存下来。...还记得fork出p->tss.eax为什么等于0了嘛,此时切换的子进程tss.eax=0,那就意味着swicth_to后,cpu寄存器的eax=0,那么等中断返回后,!fork()条件就变成了真!

1.3K40

80386的分段机制、分页机制和物理地址的形成

5、linux中的段机制 从2.2 版开始,Linux 让所有的进程(或叫任务)都使用相同的逻辑地址空间,因此就没有必要使用局部描述符表LDT。...按Intel 的规定,每个进程有一个任务状态段(TSS)和局部描述符表LDT,但Linux 也没有完全遵循Intel 的设计思路。...如前所述,Linux进程没有使用LDT,而对TSS 的使用也非常有限,每个CPU 仅使用一个TSS。...TSS 描述符存放在GDT 中,它是GDT 中的一个表项,由中断描述符表(IDT)中的任务门(存放TSS段的选择符)装入TR来进行索引。...8、linux 中的分页机制 Linux 的分段机制使得所有的进程都使用相同的段寄存器值,这就使得内存管理变得简单,也就是说,所有的进程都使用同样的线性地址空间(0~4GB)。

91230

80386的分段机制、分页机制和物理地址的形成

5、linux中的段机制 从2.2 版开始,Linux 让所有的进程(或叫任务)都使用相同的逻辑地址空间,因此就没有必要使用局部描述符表LDT。...按Intel 的规定,每个进程有一个任务状态段(TSS)和局部描述符表LDT,但Linux 也没有完全遵循Intel 的设计思路。...如前所述,Linux进程没有使用LDT,而对TSS 的使用也非常有限,每个CPU 仅使用一个TSS。...TSS 描述符存放在GDT 中,它是GDT 中的一个表项,由中断描述符表(IDT)中的任务门(存放TSS段的选择符)装入TR来进行索引。...8、linux 中的分页机制 Linux 的分段机制使得所有的进程都使用相同的段寄存器值,这就使得内存管理变得简单,也就是说,所有的进程都使用同样的线性地址空间(0~4GB)。

1.3K50

Linux从头学10:理解了这三个概念,才能彻底理解【任务管理】和【任务切换】

LDT:局部描述符TSS: 任务状态段 TCB: 任务控制块 x86 系统中的保护模式,给系统的安全性提供了很大的保障,但是在我们之前的文章中,一直都淡化了特权级别这个概念。...在 Linux 应用层,我们会严格的区分进程、线程,但是在系统的底层,这样的区分界限已经比较模糊了,用任务 task 来称呼更通用些。...TSS 也有起始地址和长度界限,也需要为它在 GDT 中创建一个段描述符。 与 LDT 类似,在处理器中也有一个寄存器 TR,用来指向当前正在执行的那个任务的 TSS。...当进行任务切换的时候: 首先,把处理器中的寄存器内容,存储到 TR 寄存器指向的 TSS 段中(即将被停止的任务); 然后,把新的任务的 TSS 段中的内容,复制到处理器的各寄存器中,并且把 TSS...看一下 Linux 2.6 内核代码中的结构体:struct task_struct{ ... },就知道 TCB 有多复杂了,有些书籍上也称之为 PCB(Process Control Block,进程控制块

67750

Linux编程(文件描述符

Linux编程世界中,不可能没听过文件描述符这个概念,我们操纵任何设备的时候,几乎都要通过它来达成的,它究竟是何方神圣呢?随我描述符科学家来一探究竟。...首先,我们在Linux下打开文件用的都是如下代码: int fd = open(... ...); 当然有同学可能会说,有时也可以用fopen(),但是fopen()只是标准IO对系统IO的封装,归根结底还是使用...很多人就想当然地以为打开嘛,就跟在windows下双击一个文件,或者双击一个文件夹一样,就是一个动作而已,其实不然,常说的打开一个文件实际上最重要的是获取这个文件的描述符描述符是用来表征这个文件的代表物...内核空间中有一堆数据结构表达一个文件的属性信息,但是用户空间看不见,只看见一个代表了这些信息的整数i,通常我们称之为文件描述符,对文件的读写和ioctl操作都是通过这个东东来达到的呢!

1.7K20

java开发系统内核:使用LDT保护进程数据和代码

(TSS),当前我们的系统内核最多支持同时运行的进程数是MAX_TASK,因此从第7个描述符往后数MAX_TASK个描述符,全都是用来指向用户进程的任务门描述符。...接下来的描述符则用来指向用户进程的局部描述符表,代码中我们设置了tasks[i].tss.ldtr的值,这个值就是上图中,全局描述符表里指向局部描述符表的那个描述符对应的下标。...我们总结一下当前进程加载的基本逻辑: 1,每一个控制台进程都对应着一个数据结构叫TSS 2,在全局描述符表中含有一个表项对应着这个TSS数据结构 3,当启动控制台进程时,内核用一个jmp指令,指令的参数就是步骤...根据加载的TSS数据结构信息,把用户进程的代码和数据加载到内存中。...同时读取TSS结构中ldtr这个变量的值 6,CPU知道TSS中ldtr变量对应的就是是全局描述符表中的一个表项,这个表项指向的是进程局部描述符表所在的位置 7,CPU根据TSS.ldtr指向的表项,获得局部描述符表的内存地址

74430

xv6(15) 进程一:数据结构

,这个数据结构就是 $PCB(Process\ Control\ Block)$,进程控制块,$Linux$ 里就是 $task_struct$ 结构体。...$ 里的内容就代表了一个任务的状态和结构: $TSS$ 是内存中的一段数据,需要在 $GDT$ 中注册专门的 $TSS$ 描述符,还有个 $TR$ 寄存器,可见部分的选择子便指向 $TSS$ 描述符。...所以 $TSS$ 是如何定位的? $TR$ 中的选择子指向 $TSS$ 描述符,通过 $TSS$ 描述符中的基址界限就能够确定 $TSS$ 的位置和大小。...按照最初设计 $CPU$ 的想法,每个任务有着自己的 $TSS$,$TSS$ 描述符,任务切换就是使 $TR$ 寄存器指向不同的 $TSS$ 描述符。...$104-limit$ 之间,$limit$ 为 $TSS$ 大小减 1,由 $TSS$ 描述符中的 $limit$ 字段指出。

19010
领券