Linux socket 摘要(一)
PS:要转载请注明出处,本人版权所有。
PS: 这个只是基于《我自己》的理解,
如果和你的原则及想法相冲突,请谅解,勿喷。
前置说明
本文作为本人csdn blog的主站的备份。(BlogID=022)
本文发布于 2016-07-04 16:31:31,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=022)
环境说明
无
前言
注意:Linux 一切皆文件
Linux 网络分层

注:Linux 网络分层,图片来自于百度图片
Linux 一个socket程序的执行流(结果就是得到一个fd,让我们能够通过fd去操作socket所创建的一个文件对象)
在用户态下:
某程序执行socket(int af, int type, int protocol)
经过系统调用层的实现
在内核态下:
会跳转到内核态执行sys_socket(),下面看其源码
SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
{
int retval;
struct socket *sock;
int flags;
/* Check the SOCK_* constants for consistency. */
BUILD_BUG_ON(SOCK_CLOEXEC != O_CLOEXEC);
BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK);
BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK);
BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK);
flags = type & ~SOCK_TYPE_MASK;
if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK))
return -EINVAL;
type &= SOCK_TYPE_MASK;
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
retval = sock_create(family, type, protocol, &sock);
if (retval < 0)
goto out;
retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK));
if (retval < 0)
goto out_release;
out:
/* It may be already another descriptor 8) Not kernel problem. */
return retval;
out_release:
sock_release(sock);
return retval;
}
这里我们注意:函数里面执行了两个函数来完成socket的功能
- sock_create()//创建一个socket
- sock_map_fd()//获得一个标号,并返回这个fd
sock_create()源代码:
static int inet_create(struct net *net, struct socket *sock, int protocol)
{
struct sock *sk;
struct inet_protosw *answer;
struct inet_sock *inet;
struct proto *answer_prot;
unsigned char answer_flags;
char answer_no_check;
int try_loading_module = 0;
int err;
if (unlikely(!inet_ehash_secret))
if (sock->type != SOCK_RAW && sock->type != SOCK_DGRAM)
build_ehash_secret();
sock->state = SS_UNCONNECTED;
/* Look for the requested type/protocol pair. */
lookup_protocol:
err = -ESOCKTNOSUPPORT;
rcu_read_lock();
list_for_each_entry_rcu(answer, &inetsw[sock->type], list) {
err = 0;
/* Check the non-wild match. */
if (protocol == answer->protocol) {
if (protocol != IPPROTO_IP)
break;
} else {
/* Check for the two wild cases. */
if (IPPROTO_IP == protocol) {
protocol = answer->protocol;
break;
}
if (IPPROTO_IP == answer->protocol)
break;
}
err = -EPROTONOSUPPORT;
}
if (unlikely(err)) {
if (try_loading_module < 2) {
rcu_read_unlock();
/*
* Be more specific, e.g. net-pf-2-proto-132-type-1
* (net-pf-PF_INET-proto-IPPROTO_SCTP-type-SOCK_STREAM)
*/
if (++try_loading_module == 1)
request_module("net-pf-%d-proto-%d-type-%d",
PF_INET, protocol, sock->type);
/*
* Fall back to generic, e.g. net-pf-2-proto-132
* (net-pf-PF_INET-proto-IPPROTO_SCTP)
*/
else
request_module("net-pf-%d-proto-%d",
PF_INET, protocol);
goto lookup_protocol;
} else
goto out_rcu_unlock;
}
err = -EPERM;
if (answer->capability > 0 && !capable(answer->capability))
goto out_rcu_unlock;
err = -EAFNOSUPPORT;
if (!inet_netns_ok(net, protocol))
goto out_rcu_unlock;
sock->ops = answer->ops;
answer_prot = answer->prot;
answer_no_check = answer->no_check;
answer_flags = answer->flags;
rcu_read_unlock();
WARN_ON(answer_prot->slab == NULL);
err = -ENOBUFS;
sk = sk_alloc(net, PF_INET, GFP_KERNEL, answer_prot);
if (sk == NULL)
goto out;
err = 0;
sk->sk_no_check = answer_no_check;
if (INET_PROTOSW_REUSE & answer_flags)
sk->sk_reuse = 1;
inet = inet_sk(sk);
inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0;
if (SOCK_RAW == sock->type) {
inet->num = protocol;
if (IPPROTO_RAW == protocol)
inet->hdrincl = 1;
}
if (ipv4_config.no_pmtu_disc)
inet->pmtudisc = IP_PMTUDISC_DONT;
else
inet->pmtudisc = IP_PMTUDISC_WANT;
inet->id = 0;
sock_init_data(sock, sk);
sk->sk_destruct = inet_sock_destruct;
sk->sk_protocol = protocol;
sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv;
inet->uc_ttl = -1;
inet->mc_loop = 1;
inet->mc_ttl = 1;
inet->mc_all = 1;
inet->mc_index = 0;
inet->mc_list = NULL;
sk_refcnt_debug_inc(sk);
if (inet->num) {
/* It assumes that any protocol which allows
* the user to assign a number at socket
* creation time automatically
* shares.
*/
inet->sport = htons(inet->num);
/* Add to protocol hash chains. */
sk->sk_prot->hash(sk);
}
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);
if (err)
sk_common_release(sk);
}
out:
return err;
out_rcu_unlock:
rcu_read_unlock();
goto out;
}
static const struct net_proto_family inet_family_ops = {
.family = PF_INET,
.create = inet_create,
.owner = THIS_MODULE,
};
这里我们只注意:
- sock_alloc()//创建一个inode(给文件系统管理),创建一个socket()对象
- pf->create()//若是tcp,则是inet_family_ops中create的值
sock_map_fd()的执行:
- sock_alloc_fd()//获得一个可用的fd
- sock_attach_fd()//把fd,file结构体,socket实例连接起来
- fd_install()//fd添加到pcb
后记
对流程的整理:
socket()
- sys_socket()
- sock_create()//创建一个socket
- sock_alloc()//创建一个inode(给文件系统管理),创建一个socket()对象
- pf->create()//若是tcp,则是inet_family_ops中create的值
- sock_map_fd()//获得一个标号,并返回这个fd
参考文献
- 无
打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)

PS: 请尊重原创,不喜勿喷。
PS: 要转载请注明出处,本人版权所有。
PS: 有问题请留言,看到后我会第一时间回复。
Linux socket 摘要(一)的更多相关文章
- linux socket高性能服务器处理框架
这个博客很多东西 http://blog.csdn.net/luozhonghua2014/article/details/37041765 思考一种高性能的服务器处理框架 1.首先需要一个内存池 ...
- Linux socket编程 DNS查询IP地址
本来是一次计算机网络的实验,但是还没有完全写好,DNS的响应请求报文的冗余信息太多了,不只有IP地址.所以这次的实验主要就是解析DNS报文.同时也需要正确的填充请求报文.如果代码有什么bug,欢迎指正 ...
- Linux socket 类封装 (面向对象方法)
/* * socketfactory.h * * Created on: 2014-7-19 * Author: root */ #ifndef SOCKETFACTORY_H_ #define SO ...
- Linux Socket 编程简介
在 TCP/IP 协议中,"IP地址 + TCP或UDP端口号" 可以唯一标识网络通讯中的一个进程,"IP地址+端口号" 就称为 socket.本文以一个简单的 ...
- Lwip:原生态的Linux socket应用如何移植到Lwip上
lwIP - A Lightweight TCP/IP stack 在上一篇中,我们了解到在OpenFastPath上如何移植原生态的Linux Socket应用程序,那么,对于另外一个老牌的小型TC ...
- OpenFastPath(2):原生态Linux Socket应用如何移植到OpenFastPath上?
版本信息: ODP(Open Data Plane): 1.19.0.2 OFP(Open Fast Path): 3.0.0 1.存在的问题 OpenFastPath作为一个开源的用户态TCP/IP ...
- Linux Socket - 基本socket链接
0x0000 Linux Socket 函数 bind listen connect accept send recv read write 0x0001 Server绑不上ip 报错位置在bind函 ...
- linux socket详解
1 linux socket编程的固定模式 server端,bind.listen.accept client端,connect client端和server端之间的一次通信: client端,wri ...
- Linux socket 编程中存在的五个隐患
前言: Socket API 是网络应用程序开发中实际应用的标准 API.尽管该 API 简单,但是 开发新手可能会经历一些常见的问题.本文识别一些最常见的隐患并向您显示如何避免它 ...
- JAVA Socket API与LINUX Socket API探究
代码 这是一个带有UI界面的JAVA网络聊天程序,使用Socket连接完成通信. JAVA服务端程序 import java.io.IOException; import java.io.InputS ...
随机推荐
- 【奶奶看了都会】云服务器ChatGLM模型fine-tuning微调,让你拥有自己的知识库
1.背景 大家好啊,上次给大家写了ChatGLM-6B的部署使用教程,[奶奶看了都会]云服务器部署开源ChatGLM-6B,让你拥有自己的ChatGPT 但是因为模型比较小的问题,所以日常工作中可能用 ...
- (Python)每日代码||2024.1.17||函数中给列表形参默认值时,该默认列表在函数中的改变会保留下来
def f(x,li=[1]): print(id(li)) li.append(x) print(li) f('a')#第一次调用函数 print() f('b')#第二次调用函数 print() ...
- 双端队列(deque)--python
Python中的双端队列(deque)是一种特殊的数据结构,它允许在队列的两端进行插入和删除操作12.双端队列可以看成栈和队列的结合3.在Python中,我们可以使用collections模块中的de ...
- MySQL数据库备份与恢复方法
MySQL数据库备份与恢复方法 mysql -uroot -p show databases; 1.导出数据库 1).MySQL命令行导出整个数据库(包含数据) 导出文件默认是存在mysql\bin目 ...
- virtualapp 应用启动源码分析
应用启动源码分析 在HomeActvity中的OnCreate方法会调用initLaunchpad private void initLaunchpad() { mLauncherView.setHa ...
- 学习go语言编程之面向对象
类型系统 类型系统是指一个语言的类型体系结构,一个典型的类型系统通常包含如下基本内容: 基础类型,如:byte.int.bool.float等 复合类型,如:数组.结构体.指针等 可以指向任意对象的类 ...
- Mqtt开发笔记:Mqtt服务器搭建
若该文为原创文章,未经允许不得转载原博主博客地址:https://blog.csdn.net/qq21497936原博主博客导航:https://blog.csdn.net/qq21497936/ar ...
- 正则函数及面向对象开发初识---day19
1.正则函数 # ### 正则函数 import re #search 通过正则匹配出第一个对象返回,通过group取出对象中的值 strvar = "1+2 3*4" obj = ...
- linux服务器界面初始--day01
linux服务器界面初始 ip add show 查看服务器网卡信息还可以使用ifconfig 局域网ip: 192.168.1.0 10.0.0.0 172.16.1.0 如果网卡没有启用,我们需要 ...
- 【Azure 事件中心】Spring Boot 集成 Event Hub(azure-spring-cloud-stream-binder-eventhubs)指定Partition Key有异常消息
问题描述 在Spring Boot应用中集成Event Hub,发送消息时指定Partition Key,日志中发现异常: 应用使用Event Hub版本为 <dependency> &l ...