本文内容为学习Linux/UNIX系统编程手册时的学习笔记与总结
用户内存空间
和一系列内核数据结构
组成。其中用户内存空间包含了程序代码及代码锁使用的变量。而内核数据结构则是用于维护进程状态信息(进程相关标识号,虚拟内存表,打开文件描述符,信号传递及处理相关信息,进程资源使用及限制,当前工作目录等信息)所有进程之父~
进程中的公共变量,入HOME,PATH等
虚拟内存是相对于物理内存RAM的一个概念,用来提高物理内存的使用效率的一个设计。
虚拟内存将所有的内存分页
(一般为4096字节一页),在进程中维护一个页表。
每张页表对应一个物理页或者是磁盘的一个空间。
设计起因
虚拟内存的优点
维基百科解释
虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存(例如RAM)的使用也更有效率。
注意:虚拟内存不只是“用磁盘空间来扩展物理内存”的意思——这只是扩充内存级别以使其包含硬盘驱动器而已。把内存扩展到磁盘只是使用虚拟内存技术的一个结果,它的作用也可以通过覆盖或者把处于不活动状态的程序以及它们的数据全部交换到磁盘上等方式来实现。对虚拟内存的定义是基于对地址空间的重定义的,即把地址空间定义为“连续的虚拟内存地址”,以借此“欺骗”程序,使它们以为自己正在使用一大块的“连续”地址。
大家熟悉的应该是C中的malloc与free方法。
然而在这两个方法背后,隐藏着另外两个方法:brk 与 sbrk。这两个方法是用来扩展堆内存区域的范围的(以虚拟内存页大小为单位来扩展)
首先,需要了解的是,每次malloc申请的内存,在通过free方法释放后,并没有放回堆内存的顶部,也就是位置没动。而是插入到一个空闲内存双向链表中,这样的特性导致内存模型如下:
那么问题来了,这里的链表pre指针和next指针存放在哪。还有free的时候是如何知道内存空间的大小的。
其实,在malloc的时候,会多申请一部分空间来存储申请得到的内存大小:
这样就能保证调用free的时候,能够知道内存块大小。
另外一个问题,就是释放内存后,pre以及next指针的数据存放问题,其实是通过在这块空闲的内存空间前面,取一部分空间来存放pre和next指针的数据:
综合上面的内容,就能够理解为何操作内存的时候,不能操作申请的内存区域之外的内存区域,这将导致用来存放长度,以及pre和next的数据被修改导致不可预知的问题。
登录的时候的用户ID即为实际用户ID,当创建新进程的时候,子进程会继承父进程的实际用户ID和实际组ID
假设登录的用户ID为A
,组ID为B
通过chmod u+s xxx
可以为xxx
可执行文件设置有效用户ID为当前进程的用户ID: A
。
通过chmod g+s xxx
可以为xxx
可执行文件设置有效组ID为当前进程的组ID:B
。
当执行xxx
可执行文件时,启动的进程有效用户ID和有效组ID即为A
和B
个人理解的是,在用户内存空间和内核内存空间都有开辟一部分内存区域用做文件IO的缓冲区使用。以减少对磁盘的直接读写,加快IO速度。
弊端: 写入到内核高速缓冲区的数据,如果碰上断电的情况,将会导致数据的丢失。
更多内容参考:Linux 内核之页高速缓存与页回写
缓冲区与特定的块设备相关联,并覆盖缓存 文件系统元数据以及跟踪正在进行的页面。缓存 仅包含停放的文件数据。也就是说,缓冲区记住了什么 在目录中,文件权限是什么,并跟踪什么 正在为特定块设备写入或读取存储器。 缓存仅包含文件本身的内容。
更多内容参考:页高速缓存里面的缓冲区高速缓存
Unix上,所有设备都有驱动程序,用来处理设备的I/O请求。驱动程序有一套公用的系统调用,包含open()、close()、read()、write()、mmap()、以及ioctl()。其中ioctl使用起来会想想对复杂一些。所有设备的接口都保持统一,隐藏了每个设备在操作方面的差异,从而满足的了I/O的操作的通用性。
某些设备是实际存在的,比如鼠标,键盘灯。而另一些设备则是虚拟的,亦即并不存在响应的硬件,但内核会(通过设备驱动程序)提供一种抽象设备,其所携带的API与真实设备无异。
设备可分为以下两种:
PIPE_BUFF
字节的数据可以保证为原子操作(可以被信号中断)pipe();
方法创建相关进程
)与管道基本一样,FIFO被称为命名管道
mkfifo()
创建相关进程
write
,read
方法来操作,它不是一个IO模型,也不是一个文件标识符。key
生成对应的唯一标示key
会生成(只生成一次)相同的标识符。key
的来源,可以通过公用一个头文件,并把key
放在头文件重定义(容易出现重复)ftok()
方法能生成唯一的key(重复概率极小,通过文件的i-Node
属性已经一个整型的低位计算而得)堆与栈中间部分
cat /proc/进程ID/maps
查看指定进程映射的共享内存以及共享库的位置信息
maps文件内容解释
基于文件内存映射
和匿名内存映射
,文件内存映射将文件内容映射进虚拟内存空间中,匿名映射通过MAP_ANONYMOUS
标记或者dev/zero
来创建,映射中的数据都会被初始化为0msymc()
系统调用请求刷新(不一定实时)文本段
以及初始化数据段
中的内容进行初始化(私有文件映射)fork()
共享相关进程的内存(共享匿名映射)什么是内存映射IO,简单的讲就是通过内存映射来实现文件的读写,替换read/write,提高效率。
通过sysconf(_SC_PAGESIZE)
查看
流Socket
和数据报Socket
流Socket
是可靠的,双向的字节流通道数据报Socket
是不可靠的、无连接的、面向消息的通信流Socket
,服务器会创建socket,然后通过bind绑定socket,然后通过listen代表接口该socket上的连接。接着通过accept阻塞等待连接的到来。客户端创建socket,通过connect连接到服务器socket上。之后两端便可以通过write和read进行通讯。数据报Socket
,服务器会创建socket,然后通过bind绑定socket,因为数据报Socket
是无连接的,所以服务器可以同时接收多个客户端的数据,通过read或者recvfrom系统调用接收数据报,其中recvfrom能够返回发送数据的socket地址。客户端创建socket之后,通过sendto向指定地址的服务器发送数据报。客户端也可以通过connect来设置一个对等地址,设置完成后就无需为发送出去的数据报设置目标地址了。write调用可以用来发送一个数据报。网络层中最底层,由设备驱动和底层物理媒介(如电话线、光纤)的硬件接口(网卡)构成。其关注的是在一个网络的物理连接上传输数据,数据单元为:帧
,每一帧有最大传输单元值(MTU)
数据链路层的上一层,其关注的是如何将包(数据)从源主机发送到目标主机,主要包含以下任务
网络层IP具备如下特性IP是无连接的
、不可靠的
IP地址:IPv4和IPv6,主要由网络ID和主机ID构成。
子网掩码:用来分开网络ID和主机ID
传输层使用最广泛的协议为用户数据报协议(UDP)
、传输控制协议(TCP)
TCP协议的特性