Linux系统编程温故知新系列 --- 01

时间:2021-06-13 00:22:00

1.大端法与小端法

大端法:按照从最高有效字节到最低有效字节的顺序存储,称为大端法

小端法:按照从最低有效字节到最高有效字节的顺序存储,称为小端法

网际协议使用大端字节序来传送TCP分节中的多字节整数(比如16位端口号,32位IPv4地址)。

2.time_wait状态

客户端(执行主动关闭的那一端)连接在收到服务器的结束报文段(FIN, ACK),并没有直接进入CLOSED状态,而是转移到TIME_WAIT状态。在这个状态,客户端连接要等待一段长为2MSL(MSL: 报文段最大生存时间)的时间,才能完全关闭。

time_wait的存在原因:

01.可靠地实现TCP全双工连接的终止

假设最终的报文段(ACK)丢失了,服务器将重新发送(FIN,ACK), 因此客户端必须维护状态信息,以允许它重新发送最终那个ACK。要是客户不维护状态信息,它将响应以一个RST(另外一种类型的TCP分节), 该分节将被服务器解释为一个错误。

02.保证让迟来的TCP报文段有足够的时间被识别并丢弃,允许老的重复分节在网络中消逝

TIME_WAIT状态的持续时间是MSL的2倍,这就足以让某个方向的分组最多存活MSL秒被丢弃,另一个方向上的应答最多存活MSL秒被丢弃,即确保网络上两个传输方向上尚未被接收到的、迟到的TCP报文段都已经消失(被中转路由器丢弃)。

time_wait的危害:

如果是服务器主动关闭连接后异常终止,则因为它总是使用同一个知名服务端口号,所以连接的TIME_WAIT状态将会导致服务器程序退出后不能立即重启

如何避免time_wait状态:

可以通过打开SO_REUSEADDR套接字选项来强制进程立即使用处于TIME_WAIT状态的连接占用的端口,即使以前建立的将该端口用作它们的本地端口的连接仍存在。

3. select/poll/epoll/kqueue对比

3.1 select .vs. poll:

01.实现细节上的区别:

select()和poll()都使用了相同的内核poll例程集合,这些poll例程有别于系统调用poll()集合本身。每个例程都返回有关单个文件描述符就绪的信息。这个就绪信息以位掩码的形式返回,其值同poll()系统调用中返回的revents字段中的比特值相关。

poll()系统调用的实现:为每个文件描述符调用内核poll例程,并将结果信息填到对应的revents字段中去

select()系统调用的实现:内核使用一组宏将内核poll例程返回的信息转化为由select()返回的与之对应的事件类型

02.API之间的区别:

select()能同时检测的文件描述符数量有上限限制(FD_SETSIZE,linux下值为1024),而poll()在理论上无此限制。

由于select()的参数fd_set同时也是保存调用结果的地方,如果要在循环中重复调用select()的话,我们必须每次都要重新初始化fd_set。而poll()因为是通过独立的两个字段events(针对输入)和revents(针对输出)来处理,从而避免每次都要重新初始化参数。

select()提供的超时精度(微秒)比poll()提供的超时精度(毫秒)高。

如果其中一个被检查的文件描述符被关闭了,通过在对应的revents字段中设定POLLNVAL标记,poll()会准确告诉我们是哪一个文件描述符被关闭了。与之相反,select()只会返回-1,并设置错误码为EBADF。

3.2 epoll .vs. select & poll

01. select & poll在监视大量的文件描述符时,性能远差于epoll。

原因: select & poll采用的都是轮询的方式,每次调用都要扫描并返回整个注册文件描述符集合,因此其检测就绪事件的算法复杂度为O(N)。epoll则在内核中维护一个事件表,epoll_wait()每次调用,都直接从该内核事件表中取得用户注册的事件,而无需反复地从用户空间读入这些事件。epoll_wait()采用回调的方式,内核检测到就绪的文件描述符时,将触发回调函数,回调函数就将该文件描述符上对应的事件插入内核就绪事件队列,内核将在适当的时机将该就绪队列中的内容拷贝到用户空间。因此epoll_wait无需轮询整个文件描述符集合来检测哪些事件已经就绪,其算法复杂度为O(1)。

02. select & poll只能工作在相对低效的LT模式,而epoll则可以工作在ET高效模式。并且epoll还支持EPOLLONESHOT事件,该事件能进一步减少可读、可写和异常等事件被触发的次数。

03. select内部是数组实现,poll内部是链表实现,所以select有最大fd限制,二者均有用户态到内核态的拷贝过程,两者的切换和数据拷贝都很消耗性能;而epoll内部是一棵红黑树,且因为epoll采取了共享内存机制,从而避免了用户态和内核态之间的切换。

3.2 kqueue .vs. epoll 

性能上:epoll每次只能更新一个兴趣列表中的文件描述符状态,换句话说,如果要在兴趣列表中更新100个文件描述符状态,就需要调用100次epoll_ctl()函数。大量的系统调用会显著地降低性能;但是,你可以通过多次使用EV_SET宏,在一次kevent调用中,更新多个感兴趣的文件描述符状态。

使用上:kevent所允许过滤的事件,除了select/poll/epoll所关注的文件I/O和超时外,还有异步I/O,文件修改通知,进程跟踪和信号处理。与此同时,epoll不支持监听普通文件或目录的文件描述符。

4.多进程 VS 多线程:

多进程——缺点

01. 创建及维护进程对系统来说都有开销——启动进程需要时间,而操作系统必须投入内部资源来管理进程

02. 一般来说子进程需要使用某种IPC机制来通知父进程有关I/O操作的状态,而进程之间的通信通常设置复杂,或是速度较慢,或者兼而有之——因为操作系统通常在进程间提供了大量保护,以避免一个进程不小心修改了另一个进程的数据

多进程——优点

01.操作系统在进程间提供的附加保护操作和更高级别的通信机制,意味着可以比线程更容易地编写安全的并发代码

02.你可以通过网络连接的不同的机器上运行独立的进程,在某些情况下,这是一个提高并行可用性和提高性能的低成本方法

多线程——缺点

如果数据要被多个线程访问,那么开发者就必须确保当每个线程访问时所看到的数据是一致的(即线程同步),这将使编程工作变得复杂,尤其是如果我们使用线程池技术来最小化需要处理的大量并发客户的线程数量时

多线程——优点

共享的地址空间,以及缺少线程间的数据保护,使得使用多线程相关的开销远小于使用多进程——操作系统有更少的簿记要做

对于C++来说,C++标准并没有为进程间通信提供任何原生支持,所以使用多进程的应用程序将不得不依赖平台相关的API来实现

5.epoll 水平触发通知. vs .边缘触发通知 (两种文件描述符准备就绪的通知模式)

水平触发通知(LT notification):如果文件描述符上可以非阻塞地执行IO系统调用,此时认为它已经就绪

边缘触发通知(ET notification):如果文件描述符自上次状态检查以来有了新的IO活动(比如新的输入),此时需要触发通知

当采用水平触发通知时,我们可以在任意时刻检查文件描述符的就绪状态。由于水平触发模式允许我们在任意时刻重复检查IO状态,没有必要每次当文件描述符就绪后就需要尽可能多地执行IO。

当采用边缘触发通知时,只有当IO事件发生时我们才会收到通知。在另一个IO事件到来之前我们不会收到任何新的通知。所以对于采用边缘触发通知的程序,在接受到一个IO事件通知后,程序在某个时刻应该在相应的文件描述符上尽可能多地执行IO;如果程序采用循环来对文件描述符执行尽可能多地IO,则应当将文件描述符设置为非阻塞的,以防止最终当没有更多IO可执行时,IO系统调用会阻塞。

总的来看,ET模式在很大程度上降低了同一个epoll事件被重复触发的次数,因此效率比LT模式要高。

6.EPOLLONESHOT标志

对于注册了EPOLLONESHOT事件的文件描述符,操作系统最多触发其上注册的一个可读、可写或者异常事件,且只触发一次,除非我们使用epoll_ctl函数重置该文件描述符上注册的EPOLLONESHOT事件。

一个用途就是确保一个socket连接在任一时刻只被一个线程处理。

References:

UNIX 网络编程,卷一

LINUX系统编程手册,下册

Linux高性能服务器编程

Linux系统编程温故知新系列 --- 01的更多相关文章

  1. Linux系统编程初探系列之一:文件编程

    系统函数 int creat(const char* filename,mode_t mode) filename:需要创建的文件名(包含路径,缺省为当前路径) mode:创建模式 常见的创建模式有: ...

  2. LINUX系统编程 由REDIS的持久化机制联想到的子进程退出的相关问题

    19:22:01 2014-08-27 引言: 以前对wait waitpid 以及exit这几个函数只是大致上了解,但是看REDIS的AOF和RDB 2种持久化时 均要处理子进程运行完成退出和父进程 ...

  3. 读书笔记之Linux系统编程与深入理解Linux内核

    前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...

  4. linux系统编程:cp的另外一种实现方式

    之前,这篇文章:linux系统编程:自己动手写一个cp命令 已经实现过一个版本. 这里再来一个版本,涉及知识点: linux系统编程:open常用参数详解 Linux系统编程:简单文件IO操作 /*= ...

  5. Linux 系统编程 学习:01-进程的有关概念 与 创建、回收

    Linux 系统编程 学习:01-进程的有关概念 与 创建.回收 背景 上一讲介绍了有关系统编程的概念.这一讲,我们针对 进程 开展学习. 概念 进程的身份证(PID) 每一个进程都有一个唯一的身份证 ...

  6. Linux 系统编程 学习:07-基于socket的网络编程2:基于 UDP 的通信

    Linux 系统编程 学习:07-基于socket的网络编程2:基于 UDP 的通信 背景 上一讲我们介绍了网络编程的一些概念.socket的网络编程的有关概念 这一讲我们来看UDP 通信. 知识 U ...

  7. Linux系统编程【3.2】——ls命令优化版和ls -l实现

    前情提要 在笔者的上一篇博客Linux系统编程[3.1]--编写ls命令中,实现了初级版的ls命令,但是与原版ls命令相比,还存在着显示格式和无颜色标记的不同.经过笔者近两天的学习,基本解决了这两个问 ...

  8. linux系统编程之错误处理

    在linux系统编程中,当系统调用出现错误时,有一个整型变量会被设置,这个整型变量就是errno,这个变量的定义在/usr/include/errno.h文件中 #ifndef _ERRNO_H /* ...

  9. Linux系统编程-setitimer函数

    功能:linux系统编程中,setitimer是一个经常被使用的函数,可用来实现延时和定时的功能. 头文件:sys/time.h 函数原型: int setitimer(int which, cons ...

随机推荐

  1. asp.net mvc 之旅—— 第三站 路由模板中强大的自定义IRouteConstraint约束

    我们在写mvc的时候,经常会配置各种url模板,比如controller,action,id 组合模式,其实呢,我们还可以对这三个参数进行单独的配置,采用的方式自然 就是MapRoute中的const ...

  2. MVC5中EF6 Code First启动慢及间隙变慢优化的实践经验(转)

    最近项目在使用EF了,mvc使用EF确实方便,因为添加功能的时候可以使用vs自动生成用ef的增.删.查.改的模板,大的提高的工作效率.但是很多人都遇到过用EF开发的程序在第一次访问的时候会比用ADO纯 ...

  3. 创建 MIME 类型////////////zzz

    用 Apache 创建 MIME 类型 在 Apache 里, MIME 类型和文件扩展名之间的映射是被存放在配置文件 "apache根目录/conf/mime.types" 里的 ...

  4. c# unity PlayerPrefs 游戏存档,直白点就是讲游戏数据本地保存下来

    在游戏会话中储存和访问游戏存档.这个是持久化数据储存,比如保存游戏记录. 我的理解是通过某个特殊的标签来保存在本地,而且该标签为key的意思,初始值不用赋值. 在游戏开发中较为实用. 暂时用到了 Se ...

  5. TypeScript学习记录

    TypeScript官网 TypeScript中文网 TypeScrpit Handbook 中文版 DefinitelyTyped The TypeScript Definition Manager ...

  6. ASP.NET MVC 4 WebAPI. Support Areas in HttpControllerSelector

    This article was written for ASP.NET MVC 4 RC (Release Candidate). If you are still using Beta versi ...

  7. Asynchronous and Distributed Programming in R with the Future Package

    Every now and again someone comes along and writes an R package that I consider to be a 'game change ...

  8. [R]统计工具包

    Wilcoxon Rank Sum and Signed Rank Tests data <-read.csv('XX.csv') wilcox.test(data$value1, data$v ...

  9. Win2012 R2虚拟机自激活(AVMA)技术

    只要你的宿主机是Windows Server 2012 R2 Datacenter且宿主机已经激活, 不管宿主机许可证是VL,OEM还是零售版,只要宿主主机处于激活状,在其上运行的任何R2 VM都将被 ...

  10. 八:python 对象类型详解四:字典

    一:字典通识: 1,字典通过键而不是偏移量来读取: 2,字典是任意对象的无序集合: 3,字典可变长.异构.任意嵌套: 4,字典属于可变映射类型: 5,对象引用表(散列表): 二:实际应用中的字典: 1 ...