`
colorlife
  • 浏览: 132310 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

linux socket学习

阅读更多

1. unix sock中,unix_find_socket_byname中使用sock_hold是为了在连接和发送消息时,增加对对端sk的引用,

避免对端sk忽然退出了

 

2. 加入hlist,intert里仅是 sock_hold 增加对sock的引用。另外就是基本功能:将节点增加到hlist的头

 

3. remove时不用list参数,是因为remove的动作很简单:将这个节点的前一节点指向这个节点的后一节点就行了!

也就是将sk脱链

sk_hashed 是判断sk是否有前节点,也就是这个sk是不是处于hlist中

 

 

4. security_sk_alloc 是在sk alloc时执行的

 

5. sk_alloc没有初始化 sk_refcnt, sk_refcnt在sock_init_data中设置,sock_init_data是用socket的一些数据进行初始化

 

6. mercury 只需 kmalloc即可,然后初始化 sk_refcnt,其它值不用管了,因为没有用到这个sk

 

7. asmlinkage 是GCC对C程序的一种扩展, #define asmlinkage __attribute__((regparm(0)))

表示用0个寄存器传递函数参数,这样,所有的函数参数强迫从栈中提取。

这个asmlinkage大都用在系统调用中,系统调用需要在entry.s文件中用汇编语言调用,所以必须要保证它符合C语言的参数传递规则,才能用汇编语言正确调用它。

syscall在38版本与之前不一样了,由SYSCALL_DEFINEx来定义,x为参数个数。如:

SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)

表示定义的是sys_socketcall,参数个数为2,int是第一个参数的类型,call是第一个参数的名称。以此类推。

 

 

8. Unix域的插口地址有两种类型。一种是常规的路径名字符串,不过不一定是以0结尾,在长度中也不包括结尾的0在内;另一种是以“\0”开头的,称为抽象地址。对于前者,unix_mkname()将其转换成一个以0结尾的字符串,并对其长度作出相应调整(195~196行)。后者类似于网络地址,unix_mkname()为之计算出一个杂凑值,并通过参数hashp返回这个杂凑值。 

对常规的字符串地址,unix_bind()根据其路径名为之在文件系统中建立一个“文件”节点。像其他特殊文件一样,这个文件实际上只是一个索引节点,而并没有用于数据的记录块,用索引节点号代替地址的杂凑值来决定将插口的sock数据结构挂入杂凑表中的哪个队列。

为什么要建立这个文件呢?这是因为Unix域允许以常规的路径名作为插口地址,这样的插口地址便于记忆,也便于通过常规的文件操作来检查一个特定的路径名是否已经在使用中。如果文件系统中已经存在具有相同路径名的文件,则unix_bind()会失败而返回出错代码EADDRINUSE。所以通常在用户程序中要在调用bind()之前先调用unlink(),将可能已经存在的同名文件先删除。应该指出,插口并不是持续存在的,其寿命决不会超过创建它的进程。当创建插口的进程exit()时,它所创建的插口也会随着已打开文件的关闭而消失。可是,为插口创建的文件(节点)却是持续存在的;即使创建它的进程exit(),甚至机器已经断电,这文件还是存在于磁盘上,所以必须特地加以删除。

 

9. sendmsg, recvmsg, write, read

第一个界面是为插口专设的,从用户程序的角度来看就是三对libc库函数,即recv()/send()、recvfrom()/sendto()以及recvmsg()/sendmsg()

第二个界面是通过常规的文件操作read()和write()这两个系统调用来进行

两个界面上的这些函数最后都是殊途同归,都归结到sock_recvmsg()和sock_sendmsg()两个函数。

从语义的角度来说,一般对“有连接”插口倾向于使用read()/write(),而对“无连接”插口则通常都使用recvfrom()/sendto()等函数。这是因为在“有连接”模式的通信中将传递的数据看成连续的“字节流”,而不保留“报文”的边界(所以其类型称为SOCK_STREAM),与文件操作的语义比较贴近。反之,“无连接”模式的通信则是“面向报文”的,所以保留报文的边界。 

 

* socket 的撤消

 关闭、撤销一个插口时,其sock结构中的计数refcnt有可能还大于1,表示还有用户,所以不能马上将这个结构释放,而只能将其refcnt计数减1,把释放结构的责任留给最后将这个计数减到0的那个进程。但是,光凭计数refcnt不足以说明该插口在逻辑上是否已经撤销,所以在sock结构中又设置了一个标志量dead,表示尽管该sock结构中的refcnt还不是0,所以还不能把数据结构最后释放,但实际上插口已经不存在了。 

 

光是对sock结构的使用和释放加以保护还不够,还要防止对sock结构的使用(例如报文的到达)和撤销在时间上相重叠。也就是说,这二者在时间上必须加以“串行化”。这样,如果插口的撤销在前,那就让撤销的过程先完成,然后再来撤销,因为在撤销的过程中可能需要对使用的后果(例如链入到receive_queue队列中的报文)加以善后处理。为此目的,内核中设置了两对加锁/解锁操作,即unix_state_rlock()/unix_state_runlock()和unix_state_wlock()/unix_state_wunlock()。当一个进程要读取sock结构中的状态信息(特别是dead)时,要先调用unix_state_rlock()加锁。这样,如果另一个进程正想要改变sock结构中的状态信息(例如想把dead变成1),就要在一个循环中(并不睡眠!)等待解锁后才能继续

 

 

* sock_wake_async(),

是干什么用的呢?让我们回顾一下server方进程是怎样通过accept()来接受连接请求的。大家知道,accept()是一个server插口接受连接请求的唯一途径,server插口是不能主动要求连接的。同时,accept()的操作从本质上说是“同步”的,如果调用accept()时尚无连接请求到来,就要睡眠等待。诚然,server方的进程可以通过O_NOBLOCK标志让accept()在没有连接请求时立即返回,但这样一来,server方进程就只好循环地或者定期地调用accept()来测试是否有连接请求到来。再考虑有时候server方进程要同时照看好几个server插口的情况,这时候server方进程就只好将O_NONBLOCK标志设成1来“轮循”各个server插口了。但是,不管时睡眠也好,或是轮循也好,server进程在此期间就不能做别的事情了。所以,O_NONB

在文件操作ioctl()中就设置了一条命令FIOASYNC,让有关进程(必须是文件的主人)可以通过这条命令向一个文件挂上号,让它在某种条件得到满足时就向该进程发送一个信号。为了这个目的,在插口的socket结构中设置了一个队列fasync_list。当server方进程希望异步地等待连接时,就通过ioctl()的FIOASYNC命令(插口也是一个已打开文件)将一个fasync_struct结构挂入到这个队列中。另一方面,我们以前也讲过,代表着一个插口的file结构中有个指针f_op,指向一个file_operations结构socket_file_ops。这个结构中的指针fasync指向函数sock_fasync(),当server方进程通过ioctl()发出FIOASYNC命令时,就会执行这个函数来完成上述将一个fasync_struct数据结构挂入到这个队列中的操作。

 

* accept

虽然这里所说插口都是“有连接”模式的,但那只是对数据(报文)而言,而控制报文实际上都是“无连接”的(否则,靠什么手段来建立最初的连接呢?)所以,这里通过skb_recv_datagram()从receive_queue队列中接收代表着连接请求的控制报文。注意datagram(“数据报”)并不表示“数据报文”,而是说以“无连接”模式传递的报文

 

* sock结构是内核中常常要动态分配是使用的,所以内核中为此专设了一个队列,通过slab机制来管理这种数据结构的缓冲区。

 

* sk_buffer

在sock结构中有几个双向队列,其中最重要的就是receive_queue和write_queue,而error_queue则仅在网络环境下才会用到。这几个队列并不采用通用的队列头结构list_head,而专门定义了一种sk_buff_head数据结构.

通常所说的“报文”是ISO的7层模型中第4层,即“传输层”的概念;

“网络层”的数据单位,称为packet(“报文分组”,或“包”)。

在Unix域的条件下,由于不涉及网络介质,所以一个报文就是一个包。每一个包都要占用一个sk_buff数据结构,所以receive_queue队列中的每个sk_buff数据结构就载运着一个到达的包,而write_queue队列中则为待发送的包。

在sock结构中还有一个特殊的sk_buff结构队列(sk_async_wait_queue),那是专为网络环境而设置的,我们在这里并不关心。

 

*

rcvbuf和sndbuf分别为接收和发送缓冲区的大小 32K

 

* Unix域中的插口地址即为一个文件(节点)的路径名。注意在unix_address结构中的name[]数组大小为0,所以unix_address结构的大小并不包括sockaddr_un结构的空间,在分配空间时要额外加上。

 

* 无连接也可以connect

事实正是这样,对于“无连接”模式的插口,可以用connect()先设置一个对方地址,然后再用send()发送报文,而实际上每次都使用预先设置好的对方地址。但是要注意,在“无连接”模式中使用connect()与在“有连接”模式中使用connect()有本质的区别。在“无连接”模式中,connect()的作用只是让内核为“本地”插口记下预设的对方地址,而并不涉及与对方之间控制报文的交互。以后则在发送的每个报文头部附上这个地址,以指明报文的目的地。至于在“有连接”模式中的connect(),则实际向对方发送一个请求连接的控制报文(指在网络环境下),并等待对方的响应。连接建立了以后,随同每个报文发送的可以只是一个连接号,而不一定要包括对方地址。

 

* msg_iov

msg_iov则指向一个结构数组,该数组中的每一个元素都是一块数据,这样一个报文的内容就可以分散在若干个互不连续的缓冲区中,而在逻辑上却连在一起,在网络环境下这是很有好处的。还有,msg_control和msg_controllen的作用是传递控制信息,在Unix域中用来在进程间传递访问权限,还可以用来传递“打开文件描述体”。

 

* 什么是RCU,在socket里用到了RCU

RCU(Read-Copy Update),顾名思义就是读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读者不需要获得任何锁就可以访问它,但写者在访问它 时首先拷贝一个副本,然后对副本进行修改,最后使用一个回调(callback)机制在适当的时机把指向原来数据的指针重新指向新的被修改的数据。这个时 机就是所有引用该数据的CPU都退出对共享数据的操作。

 

因此RCU实际上是一种改进的rwlock,读者几乎没有什么同步开销,它不需要锁,不使用原子指令,而且在除alpha的所有架构上也不需要内存 栅(Memory Barrier),因此不会导致锁竞争,内存延迟以及流水线停滞。不需要锁也使得使用更容易,因为死锁问题就不需要考虑了。写者的同步开销比较大,它需要 延迟数据结构的释放,复制被修改的数据结构,它也必须使用某种锁机制同步并行的其它写者的修改操作。读者必须提供一个信号给写者以便写者能够确定数据可以 被安全地释放或修改的时机。有一个专门的垃圾收集器来探测读者的信号,一旦所有的读者都已经发送信号告知它们都不在使用被RCU保护的数据结构,垃圾收集 器就调用回调函数完成最后的数据释放或修改操作。 RCU与rwlock的不同之处是:它既允许多个读者同时访问被保护的数据,又允许多个读者和多个写者同时访问被保护的数据(注意:是否可以有多个写者并 行访问取决于写者之间使用的同步机制),读者没有任何同步开销,而写者的同步开销则取决于使用的写者间同步机制。但RCU不能替代rwlock,因为如果 写比较多时,对读者的性能提高不能弥补写者导致的损失。

分享到:
评论

相关推荐

    linux socket学习.pdf

    本篇文章将根据给定文件“linux socket学习.pdf”的内容进行展开,重点讨论 socket 的定义、如何创建 socket 以及 socket 与其他常见 I/O 操作的区别。 #### 二、理解 Socket ##### 2.1 定义 Socket Socket 可以...

    Linux Socket学习

    ### Linux Socket 学习知识点概览 #### 一、Socket 编程简介 在 Linux 下进行 Socket 编程是实现网络通信的一种基本方法。Socket 可以被理解为一种特殊的文件描述符,它允许进程之间通过网络进行通信,无论是本地...

    Linux Socket教程.zip

    Linux Socket学习(十六).txt和Linux Socket学习(十七).txt可能涉及到了更高级的主题,如多路复用I/O,如select()、poll()或epoll(),这些工具可以帮助程序同时处理多个Socket连接。 Linux Socket学习(十四)....

    实战Linux socket编程Linux Socket Programming By Example

    《实战Linux Socket编程》是...总之,《实战Linux Socket编程》的配套源代码是一个宝贵的资源,它使学习者能够动手实践,从而更好地掌握网络编程的核心概念和技术,对于提升Linux系统下的网络编程能力具有重要意义。

    LinuxSocket示例代码

    在IT行业中,Linux Socket是进行网络通信的重要工具,尤其对于系统和网络程序员来说,理解和掌握Linux Socket编程至关重要。本示例代码提供了客户端(client)和服务器端(server)的实现,帮助初学者深入理解如何在...

    实战Linux Socket编程

    在IT领域,Linux Socket编程是网络通信的核心技术之一,它为开发者提供了在Linux操作系统上实现进程间通信(IPC)和网络通信的接口。本实战指南将深入探讨这一主题,帮助你掌握如何在Linux环境中构建高效的网络应用...

    socket_test.zip_Linux下的socket_linux socket_linux socket server_l

    在Linux操作系统中,Socket是一种进程间通信机制,它允许不同进程或者不同计算机之间的通信。本教程将深入探讨Linux下的socket编程,包括服务器和客户端的实现。我们主要关注以下几个知识点: 1. **Socket基本概念*...

    linuxsocket.zip

    本压缩包“linuxsocket.zip”包含了基于TCP/IP协议的socket通信测试代码,是学习Linux应用编程的一个实用资源。这里我们将深入探讨Linux TCP/IP socket编程的相关知识点。 1. **TCP/IP协议栈**:TCP/IP协议栈是...

    《实战 Linux Socket编程》练习代码

    通过本书的学习,读者可以掌握如何在Linux环境中使用Socket进行网络通信,构建高性能、稳定的网络应用。下面将根据提供的压缩包文件名“实战 Linux Socket编程代码”来解析其中可能包含的知识点。 1. **Socket基础...

    linux socket网络驱动深度分析

    在Linux操作系统中,Socket接口是应用程序与网络协议交互的主要接口,它允许程序通过网络发送和接收数据。在本文中,我们将深入探讨“Linux Socket网络驱动深度分析”这一主题,特别是当应用尝试创建一个用于捕获...

    实战Linux Socket编程.rar

    Linux Socket编程是网络编程的重要组成部分,它为开发者提供...通过这个实战教程,开发者将学习如何在Linux环境中创建和管理Socket,实现网络通信功能,这对于开发服务器应用、网络工具或分布式系统是至关重要的技能。

    Linux Socket

    Linux Socket是Linux操作系统中用于进程间通信(IPC)的一种接口,它允许程序通过网络协议进行数据传输。在本文中,我们将深入探讨Linux ...通过IBM技术论坛的文章,你可以更深入地了解和学习Linux Socket的各种细节。

    Linux Socket Programming (Linux 套接字编程)

    ### Linux Socket Programming (Linux 套接字编程) #### 知识点概览: 1. **Socket编程基础** ...通过以上知识点的学习,读者可以深入了解Linux环境下的Socket编程,并能够掌握如何设计和实现网络通信程序。

    linux socket 实战编程pdf及源码

    Linux Socket实战编程是深入理解网络通信机制的...总的来说,这份资源对于想要深入理解和精通Linux Socket编程的IT从业者来说是一份宝贵的资料,通过学习和实践,可以显著提升网络编程能力,为职业发展打下坚实基础。

    linux socket programming

    Gay撰写,为读者提供了丰富的实例和深入的理论知识,是学习Linux Socket编程的绝佳资源。 **二、基本Socket概念** ### 1. Socket简介 在Linux环境下,Socket是一种进程间通信(IPC)的方式,它提供了一种在两个...

    Linux Socket两则示例

    学习如何在Linux环境中编写Server/Client程序,能帮助开发者掌握网络通信的基础,进一步扩展到HTTP、FTP等上层协议的实现。这两个示例提供了很好的实践平台,可以帮助初学者巩固理论知识,同时为进阶的网络编程打下...

    linux下的socket聊天室程序

    10. **学习资源**:学习Socket编程,可以参考《UNIX Network Programming》等经典书籍,同时网上有许多关于Linux Socket编程的教程和示例代码可供学习。 总之,"Linux下的socket聊天室程序"是一个很好的实践项目,...

    实战Linux Socket 编程.rar

    本资源“实战Linux Socket编程”旨在帮助你深入理解并掌握这一关键技能,尤其对于那些希望在嵌入式领域有所建树的开发者来说,它是不可或缺的学习资料。 在Linux系统中,Socket编程主要涉及以下几大知识点: 1. **...

    Linux Socket Programming By Example

    《Linux Socket编程示例》...以上仅为《Linux Socket编程示例》部分章节的知识点总结,实际书中还包含了更多深入的技术细节和实战案例,对于希望掌握Linux环境下网络编程技术的学习者而言,是一本不可多得的参考书籍。

Global site tag (gtag.js) - Google Analytics