zoukankan      html  css  js  c++  java
  • Socket与系统调用深度分析

    • 实验要求
    • Socket API编程接口之上可以编写基于不同网络协议的应用程序;
    • Socket接口在用户态通过系统调用机制进入内核;
    • 内核中将系统调用作为一个特殊的中断来处理,以socket相关系统调用为例进行分析;
    • socket相关系统调用的内核处理函数内部通过“多态机制”对不同的网络协议进行的封装方法;

    请将Socket API编程接口、系统调用机制及内核中系统调用相关源代码、 socket相关系统调用的内核处理函数结合起来分析,并在X86 64环境下Linux5.0以上的内核中进一步跟踪验证。

    • Socket API编程接口
    •     创建socket      

        UNIX/Linux的一个哲学:所有的东西都是文件,socket也不例外,可读。可写,可控制,可关闭的文件描述符。socket基础API在sys/socket.h下面的socket系统调用可以创建一个socket。

        

    1 #include <sys/types.h>
    2 #include <sys/socket.h>
    3 int socket(int domain,int type, int protocol);  

        

    •     命名socket

    #include <sys/types.h>
    #include <sys/socket.h>
    
    int bind(int sockfd,const sockaddr* my_addr,socklen_t addrlen);

         客户端通常不需要命名socket采用的是匿名方式,操作系统自动分配的socket地址(客户端使用的就是这个分配的一个随机的非知名端口号)。

        

    •     监听socket

         socket被命名之后还不能马上接受客户的连接,需要创建一个监听队列存放待处理的客户连接。
    服务器通过listen调用被动的接连接。

    #include <sys/socket.h>
    
    int listen(int sockfd, int backlog);

     

    • 接受连接

    #include <sys/types.h>
    #include <sys/socket.h>
    int accept(int sockfd,struct sockaddr *addr, socklen *addrlen);

     accept调用对于客户端的网络断开毫不知情。只是从监听队列当中取出连接,不论连接处于何种状态。

    • 发起连接

    客户端通过connect调用主动的与服务器建立连接。

    #include <sys/types.h>
    #include <sys/socket.h>
    int connect(int sockfd,const struct sockaddr *serv_addr,socklen_t addrlen);
    • 关闭连接

    #include <unistd.h>
    int close(int fd);

    fd是待关闭的socket的描述符,将fd的引用计数减一只有当引用计数为0的时候才真正的关闭连接。一次fock将是的父进程当中打开的socket引用计数加一。因此必须都关闭才会真正的将连接关闭。

    • 系统调用机制

        

     

    如上图,系统调用执行的流程如下:

    1. 应用程序 代码调用系统调用( xyz ),该函数是一个包装系统调用的 库函数 ;
    2. 库函数 ( xyz )负责准备向内核传递的参数,并触发 软中断 以切换到内核;
    3. CPU 被 软中断 打断后,执行 中断处理函数 ,即 系统调用处理函数 ( system_call);
    4. 系统调用处理函数 调用 系统调用服务例程 ( sys_xyz ),真正开始处理该系统调用;
    • socket相关系统调用分析

      基于上次实验构建的Menu OS系统来进行本次的socket系统调用内核处理函数的跟踪分析

      即通过在Menu OS系统上运行TCP客户端/服务器程序,然后用gdb设置断点来跟踪分析socket内核处理函数。

      使用跟踪分析 ~/Linux 内核的启动过程的 -s 和 -S 选项启动 MenuOS 系统。

    $ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

    •  打开一个新的终端执行 gdb
    # 打开 GDB 调试器
    $ gdb
    
    # 在 GDB 中输入以下命令:
    
    # 在 gdb 界面中 targe remote 之前加载符号表
    (gdb)file linux-3.18.6/vmlinux 
    
    # 建立 gdb 和 gdbserver 之间的连接
    (gdb)target remote:1234
    • 设置断点
    # 断点的设置可以在target remote之前,也可以在之后
    (gdb)break #start_kernel# 
    
    # 按 c 让qemu上的Linux继续运行
    (gdb)c      

    只需在断点处输入list即可查看相应的内核处理函数,,比如__sys_listen和__sys_bind源码如下:

    int __sys_listen(int fd, int backlog)
    {
        struct socket *sock;
        int err, fput_needed;
        int somaxconn;
    
     sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
            somaxconn = sock_net(sock->sk)->core.sysctl_somaxconn;
            if ((unsigned int)backlog > somaxconn)
                backlog = somaxconn;
    
     err = security_socket_listen(sock, backlog);
            if (!err)
                err = sock->ops->listen(sock, backlog);
    
     fput_light(sock->file, fput_needed);
        }
        return err;
    }
    int __sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen)
    {
        struct socket *sock;
        struct sockaddr_storage address;
        int err, fput_needed;
    
        sock = sockfd_lookup_light(fd, &err, &fput_needed);
        if (sock) {
            err = move_addr_to_kernel(umyaddr, addrlen, &address);
            if (!err) {
                err = security_socket_bind(sock,
                               (struct sockaddr *)&address,
                               addrlen);
                if (!err)
                    err = sock->ops->bind(sock,
                                  (struct sockaddr *)
                                  &address, addrlen);
            }
            fput_light(sock->file, fput_needed);
        }
        return err;
    }
  • 相关阅读:
    ExtJS4 Panel中嵌套PDF
    从 JavaScript 数组去重谈性能优化(转)
    js中top、parent、frame
    “N”在Sql Server字段类型中的重要性 (转)
    IE下lineheight的BUG解决 (转)
    ExtJS4 Dialog
    Chrome启动后打开第一个网页很慢的解决方案(转)
    ExtJS4 Grid改变单元格背景颜色
    form表单
    Detect IFrame Load Event 探索Iframe的加载事件
  • 原文地址:https://www.cnblogs.com/smjsoftware/p/12070191.html
Copyright © 2011-2022 走看看