Linux协议栈(9)——应用层实现

简介:

Linux协议栈(9)——应用层实现

一般Linux开发程序员来看,外部的设备都是普通文件,都可以通过读写访问来实现发送和接收数据包。但是网卡有些意外,因为每个层次使用了不同的通信协议,建立连接需要指定许多选项,不能通过打开设备来完成这些任务。后来就有了套接字的特殊结构,具体怎么来的就不说了就是一个美国政府和伯克利分校的项目中诞生的,现在已经成为了工业标准,在POSIX标准中也定义了套接字,当然linux必然实现了套接字了。

使用套接字的时候需要区分地址和协议族(是ipv4还是ipv6),区分是基于流的还是数据报的(是TCP还是UDP)。

            本章会对基本的套接字数据结构及使用进行说明介绍。

内核与用户空间套接字之间的接口实现在C标准库中,使用socketcall系统,该函数是一个多路分解器。

 

1.1.1.1  socket数据结构

socket 位于传输层协议之上,屏蔽了不同网络协议之间的差异。

socket 是网络编程的入口,它提供了大量的系统调用,构成了网络程序的主体

  在Linux系统中,socket 属于文件系统的一部分,网络通信可以被看作是对文件的读取,使得我们对网络的控制和对文件的控制一样方便。

定义在文件include/linux/net.h中。

struct socket {

        socket_state            state;

 

        short                   type;

 

        unsigned long           flags;

 

        struct socket_wq __rcu  *wq;

 

        struct file             *file;

        struct sock             *sk;

        const struct proto_ops  *ops;

};

其中state表示套接字的链接状态,定义在

include/uapi/linux/net.h文件中

typedef enum {

        SS_FREE = 0,                    /* not allocated                */

        SS_UNCONNECTED,                 /* unconnected to any socket    */

        SS_CONNECTING,                  /* in process of connecting     */

        SS_CONNECTED,                   /* connected to socket          */

        SS_DISCONNECTING                /* in process of disconnecting  */

} socket_state;

            其中proto_ops指针变量指向一个数据结构,定义在文件:

include/linux/net.h.结构中包含的sock指针,指向sock结构。

关于socketcall系统调用,可以在linux系统调用实现机制详解(内核4.14.4)

文章中查看,有描述到该系统调用。该系统调用是网络相关系统调用的入口。

1.1.1.2  接收数据

使用recvfrom和recv以及文件相关的readv和read函数来接收数据。以recvfrom为例,如果调用recvfrom内核中的代码函数是sys_recvfrom。

定义在net/socket.c 文件中。

SYSCALL_DEFINE6(recvfrom, int, fd, void __user *, ubuf, size_t, size,

                unsigned int, flags, struct sockaddr __user *, addr,

                int __user *, addr_len)

            函数会先调用sockfd_lookup_light函数,从查找对应的sock.没找到则退出。

            然后调用sock_recvmsg(特定于协议,tcp使用tcp_recvmsg,udp使用udp_recvmsg),从队列中获取分组,如果没有就阻塞。

最后调用move_addr_to_user函数,将数据从内核移动到用户空间。

1.1.1.3  发送数据

发送该数据可以使用两个与网络有关的库函数(sendto和send)或文件层的write和writev函数。

            以sys_sendto为例,定义如下:

SYSCALL_DEFINE6(sendto, int, fd, void __user *, buff, size_t, len,

                unsigned int, flags, struct sockaddr __user *, addr,

                int, addr_len)   

            先调用 sockfd_lookup_light 函数获得 sock ,如果不存在则退出接着调用 move_addr_to_kernel 函数,将数据从用户层复制到内核。最后调用(协议相关的) sock_sendmsg 函数来发送。
目录
相关文章
|
1月前
|
存储 Shell Linux
【Shell 命令集合 磁盘管理 】⭐⭐ Linux 显示当前shell会话中的目录栈 dirs命令使用教程
【Shell 命令集合 磁盘管理 】⭐⭐ Linux 显示当前shell会话中的目录栈 dirs命令使用教程
27 0
|
1月前
|
Shell Linux C语言
【Shell 命令集合 磁盘管理 】Linux 显示当前shell会话中的目录栈 dirs命令使用教程
【Shell 命令集合 磁盘管理 】Linux 显示当前shell会话中的目录栈 dirs命令使用教程
36 1
|
2月前
|
传感器 网络协议 物联网
在Linux中搭建Mosquitto MQTT协议消息服务端并结合内网穿透工具实现公网访问
Mosquitto是一个开源的消息代理,它实现了MQTT协议版本3.1和3.1.1。它可以在不同的平台上运行,包括Windows、Linux、macOS等。mosquitto可以用于物联网、传感器、移动应用程序等场景,提供了一种轻量级的、可靠的、基于发布/订阅模式的消息传递机制。
|
17天前
|
网络协议 Linux SDN
虚拟网络设备与Linux网络协议栈
在现代计算环境中,虚拟网络设备在实现灵活的网络配置和隔离方面发挥了至关重要的作用🔧,特别是在容器化和虚拟化技术广泛应用的今天🌐。而Linux网络协议栈则是操作系统处理网络通信的核心💻,它支持广泛的协议和网络服务🌍,确保数据正确地在网络中传输。本文将深入分析虚拟网络设备与Linux网络协议栈的关联,揭示它们如何共同工作以支持复杂的网络需求。
|
30天前
|
监控 Linux 调度
【Linux 应用开发 】Linux 下应用层线程优先级管理解析
【Linux 应用开发 】Linux 下应用层线程优先级管理解析
48 0
|
消息中间件 监控 安全
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
探究如何在Linux系统中修改进程资源限制:四种方法调整进程限制,让你的系统高效运行(包含应用层getrlimit和setrlimit API)
46 0
|
1月前
|
Linux 网络安全
Linux NFS协议详解
Linux NFS协议详解
33 5
|
3月前
|
网络协议 Linux C++
Linux C/C++ websocket协议与服务器实现
Linux C/C++ websocket协议与服务器实现
69 0
|
3月前
|
存储 网络协议 Linux
Linux C/C++ 开发(学习笔记九 ):DNS协议与请求的实现
Linux C/C++ 开发(学习笔记九 ):DNS协议与请求的实现
55 0
|
4月前
|
网络协议 Linux 数据处理
Linux网络编程(各种协议模型的基础知识)
Linux网络编程(各种协议模型的基础知识)
45 0