一切皆文件,文件类型为普通,目录,管道,socket,链接,块设备,字符设备
cd /proc/2305/fd/
该进程打开了6个文件描述符,三个为字符设备即012,三个为socket即345,socket的两类协议簇,即inet与unix。其中3是ipv4的,4是unix,5是ipv6的。
查看man netstat会看得比较清楚
man netstat所看到的
Active Internet connections (TCP, UDP, raw)
The protocol (tcp, udp, raw) used by the socket.
Active UNIX domain Sockets
The protocol (usually unix) used by the socket.
w/o server是什么意思
Active Internet connections (w/o servers)
Active UNIX domain sockets (w/o servers)
-p, --program
Show the PID and name of the program to which each socket belongs.
-l, --listening
Show only listening sockets. (These are omitted by default.)
-a, --all
Show both listening and non-listening sockets. With the --interfaces option, show interfaces that are not marked
Unix域协议并不是一个实际的协议族,而是在单个主机上执行客户/服务器通信的一种方法,它其实是IPC(InterProcess Communication)进程间通信中的一种,顺便提一下,
进程间通信可用如下方式:管道(半双工),FIFOS(命名管理),流管道(全双工),命令流管道,消息队列,信号量,共享内存,套接口,流
IPC是一种标准的Unix通信机制。分类LPC(本地)与RPC(网络)
前几种通常限于同一台主机的各个进程间通信,后两种可以是不同主机上的各进程间通信。与网络通信不同,网络中双方确认需要IP和端口号,而在同一台机器上的2个进程则不需要这么麻烦,
如果写过管道通信的例子,则这里类似于管道,需要定义是一个用于通信的文件(不能是系统中已有的文件)
Unix域提供两类套口:字节流套接口和数据报套接口。使用Unix域套接口的理由有三个:
1,在源自Berkeley的实现中,Unix域套接口往往比通信两端位于同一个主机的TCP套接口快出一倍。
2,Unix域套接口可用于同一个主机上的不同进程之间传递描述字。
3,Unix域套接口较新的实现把客户的凭证(用户ID和组ID)提供给服务器,从而能够提供额外的安全检查措施。
这两天之前在看UNIX socket中的实现,想着试试他的性能跟TCP/IP有什么区别,如果它的性能还不及TCP/IP的话,那么他也没有什么存在的意义。
写了一个简单的echo server,简单的测试了几组数据,然后发现其性能确实比TCP/IP性能要高,数值比较接近UNIX网络编程里提到的2倍。
socket的就是走网络,普通文件的就是走磁盘IO。
为了将不同的类型的I/O与对应的文件描述符绑定,则是需要不同的初始化函数的。文件i/o与网络i/o
普通文件就通过open函数,指定对应的文件路径,操作系统通过路径能够找到对应的文件系统类型,如ext4啊,fat啊等等。
网络就通过socket函数来初始化,socket函数就通过(domain, type, protocol)来找到对应的网络协议栈,比如TCP/IP,UNIX等等。
所以网络相关的调用,如listen,connect, bind等等,第一步基本上就是通过文件描述符找到对应的内核socket结构,然后在进行对应的操作。
在socket层内核完成的就是一个interface功能,或许也可以叫做桥接模式(bridge pattern)。
内核支持某功能
由于LVS像iptables一样是工作在内核层,所以只需要安装模块ip_vs就可以了,并没有后台进程在跑
内核空间与用户空间工具
netfilter/iptables
ipvs/ipvsadm
kvm/qemu
drbd/
ll /proc/sys/fs/inotify #列出文件目录,出现下面的内容,说明服务器内核支持inotify
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_queued_events
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_user_instances
-rw-r--r-- 1 root root 0 Mar 7 02:17 max_user_watches
备注:Linux下支持inotify的内核最小为2.6.13,可以输入命令:uname -a查看内核
CentOS 5.X 内核为2.6.18,默认已经支持inotify
开发和维护内核是一件很繁杂的工作,因此,只有那些最重要或者与系统性能息息相关的代码才将其安排在内核中。其它程序,比如GUI,管理以及控制部分的代码,一般都会作为用户态程序。在linux系统中,把系统的某个特性分割成在内核中和在用户空间中分别实现一部分的做法是很常见的(比如linux系统的防火墙就分成了内核态的Netfilter和用户态的iptables)。然而,内核程序与用户态的程序又是怎样行通讯的呢?
答案就是通过各种各样的用户态和内核态的IPC(interprocess communication )机制来实现。比如系统调用,ioctl接口,proc文件系统以及netlink socket,本文就是要讨论netlink socekt并向读者展示这种用网络通讯接口方式实现的IPC机制的优点。
用户态与内核态通信
多数的 Linux 内核态程序都需要和用户空间的进程交换数据,但 Linux 内核态无法对传统的 Linux 进程间同步和通信的方法提供足够的支持!本文就总结下常见的ipc,
1.getsockopt/setsockopt
2.mmap mmap加载文件后注意还要mknod
3.netlink/socket
4.proc/seq
(1)切记不能访问已经卸载的一个proc文件,否则会导致kernel panic;
(2)注意不要删除正在调用的问proc文件。因为文件的入口项不存在关联的作者,文件的调用也并没有作用到模块的引用计数上;
(3)勿注册两个同名的proc文件,这样将导致入口项无法区分。
以上这些都是proc文件的缺点,也是使用时必须注意的地方。所以,现在推荐使用seq_file 和sys_fs。
Seq_file File System
针对proc文件的不足而诞生了Seq_file。
Seq_file的实现基于proc文件。使用Seq_file,用户必须抽象出一个链接对象,然后可以依次遍历这个链接对象。这个链接对象可以是链表,数组,哈希表等等。
5.copy_from_user/copy_to_user 这个与mmap的类似都依赖于一个字符设备文件
6.文件,严格来说不算
用户与内核之间的通信主要有内核启动参数、模块参数、sysfs、procfs、sysctl、netlink、seq_file、系统调用、debug、relayfs等等。
内核启动参数:简单的说linux使用bootloader向开发者提供接口向内核启动传输一个参数从而控制内核启动行为。
模块参数:写过内核参数的对这个很了解,使用module_param可以在加载内核模块时输入用户参数。
sysfs和procfs都是获取内核行为的方式。主要区别是sysfs除了用于访问内核状态、计算机属性、进程状态信息之外还会对设备进行管理。
sysctl:用户可以通过sysctl配置内核参数。
seq_file: seq_file是在procfs的基础上发展起来的,主要弥补了profs中内核向用户输出大量数据时的多次读写以及速度慢的问题。
系统调用:是实现用户与内核通信的一种软中断方式。
bebug:是一个虚拟文件系统,主要用于内核开发者调试信息时向用户空间输出调试信息。
relayfs:relayfs是一个快速的转发(relay)数据的文件系统,它为那些需要从内核空间转发大量数据到用户空间的工具和应用提供了快速有效的转发机制。
用户态进程间通信
常见的进程间通信方式主要有:pipe、有名管道、信号量、消息队列、共享内存、信号量以及套接字。但是上面的通信方式都不能实现用户与内核之间的交互。
表1 常见进程间通信方式
通信方式 |
无法实现内核与用户之间通信原因 |
管道(不包括命名管道) |
局限于父子进程间的通信。 |
消息队列 |
在硬、软中断中无法无阻塞地接收数据。 |
信号量 |
无法介于内核态和用户态使用。 |
共享内存 |
需要信号量辅助,而信号量又无法使用。 |
套接字 |
在硬、软中断中无法无阻塞地接收数据。 |
表2 用户与内核通信方式对比
通信方式 |
通信方式类别 |
procfs、debug、sysfs、relayfs、 |
基于文件系统的通信方式 |
系统调用、sysctl |
用户空间发起 |
内核启动参数、模块参数 |
用户设置内核参数 |
seq_file |
内核向用户输出信息 |
从表2可以看出,用户态与内核态之间的通信要么基于文件系统,要么是用户与内核单向通信,有没有用户与内核实现双向通信的方式?netlink基于sock,实现了用户与内核之间小量数据之间的交互。
系统调用与标准库函数实现之间的差异。
1965年,荷兰学者Edsger Dijkstra提出的信号量(Semaphores)机制是一种卓有成效的进程同步工具,在长期广泛的应用中,信号量机制得到了极大的发展,它从整型信号量经记录型信号量,进而发展成为“信号量集机制”,现在信号量机制已经被广泛的应用到单处理机和多处理机系统以及计算机网络中。
以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。为了完成这个过程,需要创建一个信号量VI,然后将Acquire Semaphore VI以及Release Semaphore VI分别放置在每个关键代码段的首末端。确认这些信号量VI引用的是初始创建的信号量。
用ipcs查看ipc相关信息。
14:20:33 8 ~:#ipcs -l
------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 67108864
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1
------ Semaphore Limits --------
max number of arrays = 128
max semaphores per array = 250
max semaphores system wide = 32000
max ops per semop call = 32
semaphore max value = 32767
------ Messages: Limits --------
max queues system wide = 973
max size of message (bytes) = 65536
default max size of queue (bytes) = 65536
ipcrm 命令
移除一个消息对象。或者共享内存段,或者一个信号集,同时会将与ipc对象相关链的数据也一起移除。当然,只有超级管理员,或者ipc对象的创建者才有这项权利啦
ipcrm用法
ipcrm -M shmkey 移除用shmkey创建的共享内存段
ipcrm -m shmid 移除用shmid标识的共享内存段
ipcrm -Q msgkey 移除用msqkey创建的消息队列
ipcrm -q msqid 移除用msqid标识的消息队列
ipcrm -S semkey 移除用semkey创建的信号
ipcrm -s semid 移除用semid标识的信号