1.3k words
消息队列SystemV除了共享内存之外,还有一个进程间通信的方式,是消息队列 我们说一切进程间通信的方式本质其实就是让不同进程看到同一份资源 这个消息队列的本质其实就是让两个进程可以同时看到这个队列,但是管理者其实还是操作系统 进程将数据块使用接口发送给操作系统,操作系统处理好之后插入到队列中,另一个进程也可以这样进行操作,对队列进行插入操作 当操作取出的接口时,给第一个进程另一个进程的数据块,给第二个进程第一个进程的数据块 那么其实这个消息队列并非一个严谨的先进先出,他是有标志的先进先出,本质上相当于两个队列,而且也不规定单向通信 这里与之前不同的其实就是标志,就是数据块的类型 操作系统对消息队列也需要进行管理,因此也有一个描述的结构体 并且由于都是SystemV标准下的结构,接口也都差不多,这里我们不过多介绍,等之后我们会对这里进行模拟实现 信号量同步这里是操作系统相关的内容,只做简单介绍,具体还是需要去读课本 我们说进程之间是具有异步性的,说白了就是我们无法确定哪个进程先执行,哪个进程后执行 这样就会造成一些问题 例如内存共享,两个进程通信时 写进程在还没写完的时候,...
728 words
System V共享内存System V是一种进程间通信的标准,在这种标准之下,本地通信的方式一般由三种,内存共享、消息队列、信号量 这里我们主要介绍共享内存 创建内存共享 这是内存共享的系统调用 第一个参数是共享内存在内核中的标识,类似于文件标识符的地位 第二个参数是创建共享内存的大小 第三个参数有两个选项IPC_CREAT和IPC_EXCL 如果只有第一个,则使用共享内存,不存在则创建后继续使用 第二个不能单独使用,两个相或之后表示创建共享内存后使用,存在则出错返回 第三种方法主要是为了确保所使用的共享一定是新鲜的 创建成功会返回共享内存的标识符,失败返回-1,错误码表示错误原因 共享内存存在内存的共享区中,可以有很多个,是被操作系统描述组织管理的 对于第一个参数,key是需要确定唯一的,类似于手机号,你自己有,别人不能再有一模一样的,并且别人想要打给你也必须输入一模一样的 我们可以使用ftok函数进行生成,只要两个参数相同,则能生成相同的key,类似于哈希函数 需要注意的是,共享内存在进程退出时是不会主动释放的,需要用户手动释放,除非系统内核关闭 释放共享内存命令行1ip...
279 words
命名管道之前我们使用的都是匿名管道,命名管道与之不同的就是他拥有实体文件,文件类型为p,而且他的文件大小永远为0 这时因为打开文件的同时也打开了缓冲区 当两个进程分别打开管道时,如果分别分配两个缓冲区,连接着管道文件本体,这样实在低效 不如直接两个进程连接同一个缓冲区 命名管道也称之为fifo,先进先出,也可以理解其是单向的 创建命名管道命令行1mkfifo fifo 函数1mkfifo("./testfifo",0666); 第一个参数是管道文件,第二个参数是权限,和open系统调用一样 他的返回值是int类型,返回值为-1时表示出创建管道失败 创建管道文件完成之后的任务就简单了 只用像正常读写文件的操作进行读写就可以了 可以使用系统调用接口,也可以使用C语言接口都是没问题的
3.5k words
池化技术池化技术其实是分治思想的一个体现,在生活中也有很多例子 例如,河水的水资源非常丰富,但是要多次从河水中取水使用是比较繁琐且低效的,尤其是当家离河流较远的时候(消耗较大),这时候我们就可以每次取一大缸水,需要使用的时候直接取水使用就可以了 进程池也是类似的思想,因为每一次fork创建子进程都需要进行系统调用,也需要消耗一定的资源,因此我们可以一次申请一定数量的进程PCB,分别分配对应的任务给他们就可以了 这实际上就是一种多进程并发运行的思想,我们可以用父进程来进行子进程的管理与任务分配、任务验收,然后让这些兄弟进程来运行不同的任务,这其中传递信息就需要用到我们前一篇所学的匿名管道 但是在这里我们先不具体分配,只是体会其中的思想即可 进程池进程池原理画成示意图就是这样的 蓝色是每一次我们fork子进程和pipe管道之后,需要关闭的接口,因为每一次的读接口都是3,所以从4、5、6以后的分别对应的就是不同的子进程的写管道 这里其实还有一个隐藏起来的bug,就是在第二个子进程以及之后的子进程fork的时候,实际上他拷贝的是父进程的文件描述符表,因此他也存在一个接口指向之前申请的写...
1.2k words
进程间通信进程设计的特点之一就是独立性,要避免其他东西影响自身的数据 但有时候我们需要共享数据或者传递信息,传统的父子进程也只能父进程传递给子进程信息 因此进程间通信还是很必要的,除此之外网络通信中所说的进程间通信本质上也是两个进程进行通信,只不过信息传递经过了繁杂的计算机网络 进程间通信有很多类型,但是利用管道进行进程间通信对我们了解底层原理还是很有帮助的,因此我们也从管道开始介绍 管道在我们学习Linux指令的时候,有一个字符是|,用于将前一个指令的输出传递给下一个指令作为输入 通过这么久的学习,我们可以大概猜测出这个管道的原理是什么样的 两个指令本质上就是两个进程,利用管道进行通信,将两个管道连接起来 如何控制这两个进程的输入输出呢,其实就用到了之前的重定向功能 头一个指令的输出进行重定向,后一个指令的输入重定向就可以实现这样的功能了 再深入一点,管道的本质其实就是一个被打开的文件,但同时能被两个进程访问,而且只能一个进程写,另一个进程读 匿名管道匿名管道通常用于父子进程的通信 父进程使用pipe函数创建管道 这个函数的参数是一个描述符数组,下标0表示读,下标1表示写...
1.3k words
什么是文件系统我们之前所说的文件读写都是通过进程对已经打开的文件进行操作,也就是对操作系统对文件所创建的结构体进行操作 那么对于磁盘中没有打开的文件是如何进行管理的 磁盘的物理结构这里我们主要讨论机械磁盘而非固态磁盘,因为机械磁盘的价格较低,而且学习之后也能更好的理解整个系统 这是机械硬盘内部的样子,有点像光盘的样子,不同的是光盘只能读,机械磁盘可以读写,而且机械磁盘是一摞的,利用这个磁头来感应出来0和1 绕着这个转轴,就是圆心,有不同的半径的圆,我们称之为磁道,同一个磁道所组成的称为柱面,而为了同时读取数据,按照不同的圆心角划分成了不同的扇区 我们可以把某一个磁道的扇区单独取出来,看成一个数组,这样就能把文件系统划分成众多这样的数组,再将其组织起来即可 这样对磁盘问题就变成了对数组的问题,存储数据到磁盘就变成了存数据到数组,从磁盘取数据就是找到数组中的位置,对磁盘的管理也就成了对数组的管理 这样一个扇区的大小是512字节,接下来就是对扇区如何进行划分管理了 扇区中的块组直接管理512字节还是过于麻烦,我们仍然需要对其进行设计才能很好的管理其中的内容 一个扇区会分成若干个这...
863 words
重定向我们在学习Linux的基本内容时候,知道>> >都可以用来表示重定向,那么重定向的本质是什么呢,其实就是更改了标号为1的文件描述符 1表示标准输出,那么我们也就可以手动实现输出重定向,将标准输出更改为我们指定的文件 1234567891011121314 1 #include<unistd.h> 2 #include<sys/types.h> 3 #include<sys/stat.h> 4 #include<fcntl.h> 5 #include<stdio.h> 6 7 int main() 8 { 9 close(1);10 int fd = open("log.txt",O_WRONLY|O_CREAT|O_TRUNC,0666);11 printf("关闭1之后新建文件标识符为%d\n",fd);12 fprintf(stdout,"输出到更改后的标准输出\n"); 13 ...
1.1k words
在Linux系统下有句名言是,Linux中一切皆文件 C语言中的文件接口在C语言中有三个数据流,分别是stdin、stdout、stderr,这三个标准文件是交给程序员来输入输出的 可以从键盘读入,显示器输出,也可以输出到文件中,那么其实在操作系统内部,他是把显示器、键盘等外设也看作是文件,向显示器输出和向磁盘文件中输出写入是没有本质区别的 C语言打开文件的函数是fopen,读取是fread、fscanf、fgets,写入是fwrite、fprintf、fputs,和基础的scanf、gets使用都是一致的,只需要在末尾加上写入的文件指针即可 fopen的返回值和三个数据流都是文件指针类型的,是FILE* 操作文件的系统调用每一种语言都有各自不同的文件操作函数,但不管语言如何改变,想要对文件进行读写都需要让操作系统帮忙,使用系统调用才能对文件进行操作 操作系统有四个系统调用 open、close、write、read open 我们主要看第一个定义,他的返回值是文件描述符fd,第一个参数是打开文件的路径,flags是你想要打开文件的方式 因为文件的打开方式比较繁多,不能每一个都设...