当前位置: 首页 > Linux

到目前为止,在学习操作系统的过程中积累的问题

时间:2023-04-06 01:57:05 Linux

,在排版中对文中的很多定义还是不是很确定,还望大佬指正。问问题1.为什么复制大文件比复制许多小文件更快。问题2.使用多线程或多进程从服务器复制文件。问题3.所以严格来说线程除了TLS没有私有变量?只要拿到指针,就可以修改其他线程的数据了。问题4.内核空间和用户空间都是虚拟内存的一部分?问题5.对于高并发的网络请求,多进程多线程不一定能满足?C语言呢?问题5.各种IPC使用场景,虽然搜索了一些资料,但感觉很片面,理解不深。问题6、使用socket、header、protocol、封装、配置开销有哪些麻烦?问题7.什么是零拷贝问题8.刷新并关闭?问题9.默认I/O流问题10.signal和sigaction的区别其他的也希望老师能看一看,确认我的理解是正确的。CPU密集型和IO密集型。由于pythonGILd的存在,python多线程不是并行而是并发,导致CPU密集型任务效率下降。IO密集型任务因为等待会挂很久,所以多线程也适用,创建线程和上下文切换比进程消耗资源少,所以速度更快。所以对于python来说,CPU密集型使用多进程,IO密集型使用多线程。对于高并发的网络请求,多进程多线程未必能满足?C语言呢?一个聊天室应用,十个通信设备各开一个线程,CPU负担很重。这个时候应用就是IO多路复用select、poll、epoll。顺便把CPU读写的负担缓存起来。和缓冲。还没看懂。并发nginx、apache、tomcat,进程切换=进程内线程切换。还没有了解使用套接字的麻烦、头部、协议、封装和配置成本?还不明白IPC、RPC和API网关第1章文件和目录之间的区别吗?在Linux中,它们都是用文件来描述的,它们的文件类型也不同。目录文件存放目录下所有文件名和inode的映射关系。rm文件时会发生什么?1)使用unlink减少链接数,2)如果链接数为0释放inode,数据块将被放入空闲空间列表;3)删除目录https://blog.csdn.net/weixin_...中的目录项为什么同一个文件系统移动文件快?因为只是删除了目录中原位置的对应关系,移动的位置增加了新的对应关系,并没有写入数据。不同文件系统使用rm+cp格式?inode-table也会占用存储空间。Chapter3Bufferingandcaching看我的文章bufferandcachehttps://segmentfault.com/a/11...Chapter7fork和vfork忘记了还没明白怎么保存密码,把密码写入环境变量第十章kill-9init发生了什么?唯一可以发送到进程ID1(init进程)的信号是那些init已经明确安装了信号处理程序的信号。这样做是为了确保系统不会意外关闭。按照上面的说法,什么都不会发生,因为init没有为SIGTERM建立信号处理程序?https://unix.stackexchange.co...第11章?CPU上下文切换分为进程上下文切换、线程上下文切换和中断上下文切换。进程和线程有什么相同点和不同点?(1)线程是调度的基本单位,进程是资源拥有的基本单位。进程是系统资源分配的最小单位。线程是cpu运行和调度的最小单位。它本质上是一组寄存器的状态。状态的抽象,例如进程是一个人,线程是这个人接收到的东西。很多事情,一个人可以做多件事,或者叫很多人每人做一件事。(2)上下文切换成本远大于线程进程的进程上下文,不仅包括虚拟内存、栈、全局变量等用户空间资源,还包括内核栈、寄存器等内核空间的状态。线程上下文切换线程本地存储(TLS)、堆栈和寄存器等。这两个上下文切换过程都是由操作系统内核完成的。与内核的这个切换过程相关的最显着的性能损失是切换出寄存器的内容。(3)进程中的线程共享地址空间,进程间通信的代价远大于线程间通信。管道、共享队列、信号、信号量和套接字(4)的创建成本远低于进程,因为线程包含的数据量比进程少,线程只需要执行相关数据,如pc、registers、stack、executionstatus第11章线程间特有的资源是https://cloud.tencent。com/dev...stackarea同时,函数在运行的时候,需要额外的寄存器来保存一些信息,比如一些局部变量。这些寄存器也是线程私有的,一个线程不可能访问另一个线程的此类寄存器信息。线程的栈区、程序计数器、栈指针和函数使用的寄存器都是线程私有的。这些信息有一个统一的名字,threadcontext,threadcontext。所以严格来说线程除了TLS没有私有变量?只要拿到指针,就可以修改其他线程的数据了。TLS->线程本地存储?该区域存储的变量是全局变量,所有线程都可以访问。是全局的,但是每个线程在访问的时候都会保存一份自己的局部变量,修改不会相互影响虽然看起来所有线程都访问同一个变量,但是全局变量是单独属于一个线程的,修改的一个线程的这个变量对其他线程不可见。实现原理类似于拥有一个全局字典。字典的键是线程id,值是共享全局变量的副本。http://blog.hacksmeta.com/201...线程共享资源代码区编译代码数据区全局变量,静态变量。堆区C/C++中malloc或new得到的数据就存放在这个区域。只要知道指针,任何线程都可以访问指针指向的数据,所以堆区也是线程共享的资源,属于进程。栈区如果一个线程可以从另一个线程的栈帧中得到一个指针,那么这个线程就可以改变另一个线程的栈区,也就是说这些线程可以任意修改属于另一个线程栈区的变量另一个线程。动态链接库动态链接部分生成的库就是我们熟悉的动态链接库。Windows下是DLL结尾的文件,Linux下是so结尾的文件。文件如果程序在运行过程中打开了一些文件,进程地址空间中也保存了打开文件的信息,进程打开的文件也可以被所有线程使用,这也是线程间的共享资源。忘记什么问题是cpu密集型以减少cpu使用率?①增加cpu②减少系统进程,线程数和锁的使用场景,请参考我的文章UNIX环境高级编程第11章遗留问题注意事项https://segmentfault.com/a/11...第14章阻塞、非阻塞阻塞和非阻塞关注的是程序在等待调用结果(消息、返回值)时的状态。阻塞调用是指在返回调用结果之前,当前线程将被挂起。调用线程只有在得到结果后才会返回。非阻塞调用是指调用不会阻塞当前线程,直到不能立即得到结果。节目时间?检查调用是否完成。SynchronousandasynchronousSynchronousandasynchronous同步和异步主要是消息通信机制(同步通信/异步通信)。所谓同步,就是当一个调用发出时,直到得到结果后调用才会返回。但是一旦调用返回,你就会得到返回值。也就是说,由调用者主动等待本次调用的结果。异步则相反。发出调用后,调用直接返回,所以没有返回结果。换句话说,当发出异步过程调用时,调用者不会立即得到结果。相反,在调用发出后,被调用者通过状态和通知通知调用者,或者通过回调函数处理调用。第15章https://www.jianshu.com/p/498...进程间通信有哪几种类型?它们的应用场景是什么?内核空间和用户空间都是虚拟内存的一部分?消息队列和管道基本都复制了4次,而共享内存(mmap、shmget)只复制了2次。1、管道是半双工的(即数据只能单向流动),有固定的读写端。它只能用于有关系的进程之间(也包括父子进程或兄弟进程之间)的通信。可以看成是一个特殊的文件,对其读写也可以使用read、write等普通函数。但它不是普通文件,不属于任何其他文件系统,只存在于内存中。应用场景?2.FIFOFIFO,又称命名管道,是一种文件类型。与无名管道不同,FIFO可以在不相关的进程之间交换数据。FIFO有一个与之关联的路径名,它作为一个特殊的设备文件存在于文件系统中。应用场景?3.消息队列消息队列是存储在内核中的消息链表。消息队列由标识符(队列ID)标识。消息队列是面向记录的,其中的消息有特定的格式和特定??的优先级。消息队列独立于发送和接收进程。当进程终止时,消息队列及其内容不会被删除。消息队列可以实现消息的随机查询,消息不一定要按照先进先出的顺序读取,也可以按照消息的类型来读取。应用场景的好处上面已经说了,就是在特殊场景下有相应的好处,比如解耦、异步、调峰系统可用性降低:系统引入的外部依赖越多,越容易挂掉向上。本来你是A系统调用BCD三个系统的接口都可以,ABCD四个系统都可以,没有问题,你加个MQ进去就行了,万一MQ挂了怎么办?MQ挂了,整个系统崩溃,你这不就完了吗?系统复杂度增加:如果硬生生加一个MQ,怎么保证消息不被重复消费?消息丢失的情况如何处理?如何保证消息传递的顺序?头大头大,问题多多,痛苦不已。一致性问题:系统处理后直接返回成功。建库成功,但是C系统写库失败,怎么办?你的数据不一致。https://zhuanlan.zhihu.com/p/...消息队列和管道基本复制4次,而共享内存(mmap、shmget)只复制2次。读取磁盘文件的第一步是通过系统调用。它首先将文件内容从磁盘拷贝到内核空间的缓冲区中,然后再将数据拷贝到用户空间,实际上是两次数据拷贝。第三步回写也需要经过两次数据拷贝。4次:1、write()从磁盘输入到A内核空间。2.写入B用户空间。3、B调用read()读入内核空间。4.从内核空间放磁盘。内存映射文件是操作系统提供的一种机制,可以减少这种不必要的数据拷贝,从而提高效率。它使用mmap()直接将文件映射到用户空间。mmap()不复制数据。真正的数据拷贝是在缺页中断时执行的。由于mmap()直接将文件映射到用户空间,所以被打断了。根据这个映射关系,处理函数直接将文件从硬盘复制到用户空间,所以只进行了一次数据拷贝,比读取两次数据拷贝好一倍。因此,内存映射的效率要高于读/写。.2次:1、输入到用户空间。2、用户空间输出。零拷贝?消息队列和管道都是内核对象,它们执行的操作也是系统调用,这些数据最终都是存放在内存中执行的。因此,不可避免地要经历4份数据。但是共享内存不同。在执行mmap或shmget时,会在内存中开辟空间,然后将这块空间映射到用户进程的虚拟地址空间,即返回值是一个指向内存地址的指针。当用户使用这个指针时,比如赋值操作,会引起从虚拟地址到物理地址的转换,数据会直接写入对应的物理内存,省去了拷贝到内核的过程。读取数据时也是类似的过程,所以一共有两个数据副本。优点:A.我们几乎可以通过发送消息的方式完全避免命名管道的同步和阻塞问题。B、我们可以通过一些方法提前查看紧急消息。缺点:A.和管道一样,每个数据块都有最大长度限制。B、系统中所有队列包含的所有数据块的总长度也有上限。四、信号量信号量(semaphore)不同于前面介绍的IPC结构,它是一个计数器。信号量用于实现进程间的互斥和同步,而不是存储进程间通信数据。信号量用于进程间同步。进程间传递数据,需要结合共享内存。信号量是基于操作系统的PV操作,程序对信号量的操作都是原子操作。每次对信号量的PV操作不限于对信号量值加1或减1,还可以加减任意正整数。支持信号量组。两用信号量:互斥量类似于互斥量,但互斥量只能通过locker->线程1和线程2->线程3进行解锁和同步5.共享内存共享内存(SharedMemory),指的是两个或多个进程共享给定的内存区域。共享内存是最快的IPC类型,因为进程直接访问内存。同步是必需的,因为多个进程可以同时运行。信号量+共享内存通常一起使用,信号量用于同步访问共享内存。传输大量数据的场景读取大量相同数据的场景6.信号使用场景接收进程在某个时间已经发生并死亡。7、Socket使用场景8、Unix域socket使用场景Linux-进程间通信(N):各种IPC使用场景Pipelines:只能用于亲属关系通信,使用范围比较狭窄。实际开发中很少用到;FIFO(命名管道):可用于任意进程之间的通信,大块数据的传输效率高。;Signal:不能传输数据,信号类型有限,只适合完成一些简单的事件通知任务,比如配置和新信号通知,一个服务通过信号通知另一个服务自己的状态;文件锁:不能用于传输数据,用于协调操作,使用文件锁实现多个进程对一个资源的排队请求,或者多个进程对系统全局资源的读写操作,可以使用文件锁来实现实现进程间读写锁的功能;XSIIPC:Sharedmemory:最高效的进程间通信方式,进程可以直接读写内存,无需任何数据拷贝,适用于多个进程共享数据,或频繁交互进程间数据量大;--推荐使用mmap方式;消息队列:在进程间传递简单的命令和控制消息,如配置更新通知、多进程到多进程通信等,可以简化代码逻辑;--建议改用全双工管道;semaphore:some资源数量为N,多个进程正在使用这个资源。为了实现进程间的互斥,可以使用初始值为N的信号量;--建议改用记录锁;socketIPC:unixdomainsocket词:一个服务同时与多个服务通信。这时候需要维护多个通信通道。使用unixsockets,可以使用linux的IO多路复用功能;--建议优先使用网络套接字;networksockets词:如果系统需要支持分布式部署,服务可能在同一个设备上,也可能在不同的设备上。这时候使用网络套接字比较合适,提高了可扩展性;第16章实现了一个具有多个客户端和单个服务器的聊天室应用程序。看我的文章多人聊天室(多线程||epoll)https://segmentfault.com/a/11...