UNIX域套接字
UNIX域套接字是单个主机上客户端与服务器通信的一种方式。允许同一台计算机上不同进程之间通过文件系统中的特殊文件(套接字文件)进行数据交换。
可以在同一台计算机上运行的两个进程之间传递打开的文件描述符。
与TCP套接字相比较,UNIX域套接字不涉及网络协议栈,因此传递速度更快,效率更高。
专注于工业物联网行业数据采集,嵌入式Linux系统裁剪,5G智慧网关软件开发等
UNIX域套接字是单个主机上客户端与服务器通信的一种方式。允许同一台计算机上不同进程之间通过文件系统中的特殊文件(套接字文件)进行数据交换。
可以在同一台计算机上运行的两个进程之间传递打开的文件描述符。
与TCP套接字相比较,UNIX域套接字不涉及网络协议栈,因此传递速度更快,效率更高。
如上节所述,poll
函数是另一个支持I/O多路转接的函数。
与select
不同的是poll
函数支持更多的条件,而非select
函数仅有的三种条件(可读、可写以及异常)。
同时poll
函数是以struct pollfd
数组类型保存文件描述符(没有文件描述符的数量限制),并为每个文件描述符指定关注的哪些条件,而select
函数则是另一种角度,为每个条件设置哪些文件描述符。
当一个进程需要从多个文件描述中读,并写入多个文件描述符中(例如TCP服务器)。
当一个进程需要对一个文件描述符同时进行读写,两者并没有前后关系。如果采用阻塞I/O,那么没有数据读就会阻塞,进而导致进程无法处理写入,写阻塞时同理。
上述问题的一个解决方法是采用多线程,每个线程中对一个描述符进行阻塞I/O,缺点是线程实现复杂,同时进程支持的线程数量有限。
文件锁的作用:当第一个进程正在读或修改文件的某个部分时,使用文件锁可以阻止其他进程修改文件的相同部分。
因此文件锁可用于多个进程之间进行同步,防止进程间的竞争状态。
Linux系统支持两组给文件加锁的不同API,分别是fcntl
与flock
。本节主要记录flock
的实现原理以及使用方式。
文件锁的作用:当第一个进程正在读或修改文件的某个部分时,使用文件锁可以阻止其他进程修改文件的相同部分。
因此文件锁可用于多个进程之间进行同步,防止进程间的竞争状态。
Linux系统支持两组给文件加锁的不同API,分别是fcntl
与flock
。本节主要记录fcntl
的实现原理以及使用方式。
任意多个进程在同一个给定字节上都可以有一把共享读锁,但一个给定字节上仅能有一个进程持有一把独占写锁。
系统调用分为两类,“低速”系统调用和其他。
“低速”系统调用指的是可能会使进程永远阻塞的一类系统调用。
非阻塞I/O则指的是当进行诸如open, read, write
等I/O操作时,这些操作不会永远阻塞。如果操作不能完成,则调用立即出错返回,以表示继续该操作将会阻塞。
一般非阻塞I/O需要不断轮询判断是否有数据要进行读写,这种情况是比较浪费CPU时间的。避免非阻塞I/O的两种方式:I/O多路转接或多线程采用阻塞I/O。
守护进程是生存期长的一种进程,在系统引导装入时启动,在系统关闭时终止。
守护进程没有控制终端,通常在后台运行,实际上是在后台的孤儿进程组中运行。
没有控制终端的原因在于不与用户交互,避免终端信号影响。
在孤儿进程组中运行的原因在于防止其获取控制终端(通过每次打开终端设备设置参数O_NOCTTY
的方式不太靠谱)。
多线程环境下,调用fork
函数创建子进程时,子进程完全继承了父进程的整个内存地址空间。
父进程中的互斥锁、多个线程在子进程中是如何处理的呢?
由于父子进程之间采用了写时复制技术,在子进程未改变互斥锁之前,父子进程对锁的状态是相同的,此时如何处理同步状态?
多线程环境下需要使用互斥量等数据来进行线程间数据同步,然而同时使用同步对象与信号处理很容易造成死锁,本文探索如何在多线程环境下来进行信号处理。
在多线程环境中,为了防止信号中断线程,通常把信号加到每个线程的信号屏蔽字中。然后安排专用线程来处理信号。
线程特定数据(thread-specific data),也称为线程私有数据(thread-private data),是线程单独的数据副本,存储在线程的私有存储空间,不与进程中其他线程共享。
线程键(pthread_key_t
),每个线程用其与自身特定数据地址进行关联。
析构函数用于线程退出时调用。通常使用malloc
为线程特定数据分配内存,析构函数通常用于释放已分配的内存。