码迷,mamicode.com
首页 > 其他好文 > 详细

Socket 与系统调用深度分析

时间:2019-12-19 19:04:42      阅读:80      评论:0      收藏:0      [点我收藏+]

标签:alt   位置   bsp   向量   lin   com   用户态   list   idt   

一、实验环境准备

uname -a

技术图片

 在本机编译linux 5.0.1 X86-64内核,重新按照64位方式编译,步骤同上一篇博客。

make x86_64_defconfig
make menuconfig
make  #编译内核

二、Socket与系统调用

1.socket

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

2.系统调用

  1. 系统调用就是为了让应用程序可以访问系统资源,每个操作系统都会提供一套接口供应用程序使用。这些接口通常通过中断来实现,linux使用0x80号中断作为系统的调用的入口。
  2. 系统调用的弊端:各个操作系统的系统调用不兼容,使用不方便,系统调用比较原始。运行库解决这两个问题,它的使用统一不会随着操作系统或编译器的变化而变化。
  3. 系统调用的原理:系统调用是运行在内核态的,而用户程序一般是运行在用户态的,操作系统一般通过中断从用户态切换到内核态。中断具有两个属性一个是中断号,一个是中断向量表,是一个数组,包含中断处理程序。一个中断号对应一个中断处理程序。中断分为硬件中断和软件中断,软件中断通常是一条指令,带有一个参数代表中断号。在linux中使用0x80来触发所有的系统调用。和中断一样系统调用都有一个系统调用号,系统调用号代表在系统调用表中的位置。

技术图片

3.系统调用表

vi linux-5.0.1/arch/sh/include/uapi/asm/unistd_64.h

技术图片

从中可以看到与socket相关的调用号。

三、GDB调试

1.启用gdb调试系统启动

vi LinuxKernel/menu/Makefile
cd menu
make rootfs

在图形化界面启动menu后,用终端打开gdb:

 技术图片

 查找资料得知,我本机是32位linux,gdb为32位,无法调试64位程序。因此,下面为基于32位linux内核的调试。

技术图片

技术图片

   在系统启动后,可以看到,内核的初始化完成了以下的函数调用过程:start_kernel > trap_init > idt_setup_traps, 其中start_kernal是内核启动的入口函数。

 2.gdb调试socket

这一次我们在__sys_listen加入断点

技术图片

可以看到,当我在Qemu中输入replyhi后,进入断点

技术图片

 在sys_socketcall加入断点,输入了replyhi后,可以看到该方法被调用了4次

技术图片

 Socket本质上是一个glibc中的函数,执行实际上是是调用sys_socketcall()系统调用。sys_socketcall()是几乎所有socket相关函数的入口,即是说,bind,connect等等函数都需要sys_socketcall()作为入口。省略号省略掉的是各种网络编程用得到的函数,全部都在这个系统调用中,socketcall是系统所有socket相关函数打大门。

SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
{
     unsigned long a[6];
     unsigned long a0, a1;
     int err;
     unsigned int len;
     if (call < 1 || call > SYS_SENDMMSG)
             return -EINVAL;
     len = nargs[call];
     if (len > sizeof(a))
             return -EINVAL;
     /* copy_from_user should be SMP safe. */
     if (copy_from_user(a, args, len))
             return -EFAULT;
     audit_socketcall(nargs[call] / sizeof(unsigned long), a);
     a0 = a[0];
     a1 = a[1];
     switch (call) {
     case SYS_SOCKET:
             err = sys_socket(a0, a1, a[2]);
             break;
     case SYS_BIND:
             err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
             break;
    //...
     default:
             err = -EINVAL;
             break;
     }
     return err;
 }

Socket 与系统调用深度分析

标签:alt   位置   bsp   向量   lin   com   用户态   list   idt   

原文地址:https://www.cnblogs.com/tanhao1410/p/12066356.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!