socket与文件描述符
在Linux编程时,无论是在操作文件还是网络操作时都能够通过文件描述符来read或者write。之前在没有接触C++的时候,不懂面向对象的那套东西。自从学习了C++以及面向对象的一些知识以后突然对Linux这套文件描述符有了稍微深刻的认识。怎么说呢,Linux这一套文件机制就相当于面向对象里面的多态,拿到一个文件描述符都可以进行read或者write。但是具体的read和wri
·
在Linux编程时,无论是在操作文件还是网络操作时都能够通过文件描述符来read或者write。之前在没有接触C++的时候,不懂面向对象的那套东西。自从学习了C++以及面向对象的一些知识以后突然对Linux这套文件描述符有了稍微深刻的认识。
怎么说呢,Linux这一套文件机制就相当于面向对象里面的多态,拿到一个文件描述符都可以进行read或者write。但是具体的read和write却跟对应文件描述符的具体实现不同。比如socket的就是走网络,普通文件的就是走磁盘IO。
下面一张UML类图大概表现出了Linux文件描述符的大概意思:
当然,为了将不同的类型的I/O与对应的文件描述符绑定,则是需要不同的初始化函数的。在C++中有构造函数跟编译器帮助搞定,在C函数里只能自己动手丰衣足食了。
普通文件就通过open函数,指定对应的文件路径,操作系统通过路径能够找到对应的文件系统类型,如ext4啊,fat啊等等。
如果是网络呢,就通过socket函数来初始化,socket函数就通过(domain, type, protocol)来找到对应的网络协议栈,比如TCP/IP,UNIX等等。
整个Linux 文件系统的结构差不多就这个意思,socket跟他绑定也是为了统一接口。
所以网络相关的调用,如connect, bind等等,第一步基本上就是通过文件描述符找到对应的内核socket结构,然后在进行对应的操作。
- SYSCALL_DEFINE2(listen, int, fd, int, backlog)
- {
- struct socket *sock;
- int err, fput_needed;
- int somaxconn;
-
- /* 通过文件描述符获得 kernel socket结构, 并且增加此结构的引用计数 */
- sock = sockfd_lookup_light(fd, &err, &fput_needed);
- if (sock) {
- /* 进行检测,看看是否满足系统设计的需求,功能上不重要 */
- somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
- if ((unsigned)backlog > somaxconn)
- backlog = somaxconn;
- /* 检测此调用是否安全 */
- err = security_socket_listen(sock, backlog);
- /* 执行具体的listen操作,TCP啊,或者是其他网络协议等等,这个ops是在socket时候绑定的 */
- if (!err)
- err = sock->ops->listen(sock, backlog);
- /* 减少kernel socket的引用计数 */
- fput_light(sock->file, fput_needed);
- }
- return err;
- }
上面就是一个典型的调用listen的内核操作。
在socket层内核完成的就是一个interface功能,或许也可以叫做桥接模式(bridge pattern)。
这就是我对socket及Linux文件描述符的理解。
更多推荐
已为社区贡献1条内容
所有评论(0)