![](https://img-blog.csdnimg.cn/20201014180756925.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Linux内核
文章平均质量分 71
Justlinux2010
新浪微博 justlinux2010
展开
-
浅谈shutdown()和close()的区别
shutdown()函数可以选择关闭全双工连接的读通道或者写通道,如果两个通道同时关闭,则这个连接不能再继续通信。close()函数会同时关闭全双工连接的读写通道,除了关闭连接外,还会释放套接字占用的文件描述符。而shutdown()只会关闭连接,但是不会释放占用的文件描述符。所以即使使用了SHUT_RDWR类型调用shutdown()关闭连接,也仍然要调用close()来释放连接占用的文件描述符原创 2014-03-10 13:15:16 · 10848 阅读 · 0 评论 -
探究Linux下参数传递及查看和修改方法
X86-64下有16个64位寄存器,其中%rdi、%rsi、%rdx,%rcx、%r8、%r9用作传递函数参数,分别对应第1个参数、第2个参数直到第6个参数,如下图所示(图片来自网络): 如果函数的参数个数超过6个,则超过的参数直接使用栈来传递。在被调用函数执行前,会先将寄存器中的参数压入堆栈,之后的访问会通过栈寄存器加上偏移位置来访问。下面我们结合程序及其反汇编的结果来看一看。C语原创 2013-09-08 18:15:17 · 4593 阅读 · 0 评论 -
IP数据包的输入与输出
IP层主要函数之间的调用关系如下图所示:上面的图主要是拷贝的《Linux内核源码剖析----TCP/IP实现上册》中的图11.3,原图中有部分错误,所以这里重新绘制了一下,并且去掉了一些冗余的部分。下面简述一下数据包传递的大致过程:一、IP数据包的输入ip_rcv()是网络层(IPv4,以下同)接收数据包的入口函数,链路层在接收到数据包后调用netif_receiv原创 2013-08-28 17:42:49 · 2115 阅读 · 0 评论 -
netpoll浅析
netpoll只是一种框架和一些接口,只有依赖这个框架和接口实现的netpoll实例,netpoll才能发挥它的功能。类似于kernel中的vfs,vfs本身并不会去做具体的文件操作,只是为不同的文件系统提供了一个框架。netpoll不依赖于网络协议栈,因此在内核网络及I/O子系统尚未可用时,也可以发送或接收数据包。当然netpoll能够处理的数据包类型也很有限,只有UDP和ARP数据包,并且只能原创 2013-08-15 10:24:11 · 4818 阅读 · 0 评论 -
Linux kernel中网络设备的管理
kernel中使用net_device结构来描述网络设备,这个结构是网络驱动及接口层中最重要的结构。该结构不仅描述了接口方面的信息,还包括硬件信息,致使该结构很大很复杂。通过这个结构,内核在底层的网络驱动和网络层之间构建了一个网络接口核心层(这个叫法引自《TCP迁移报告》),这个中间层类似于文件子系统的VFS。这样底层的驱动程序就不需要过多地关注上层的网络协议,只需要通过内核提供的网络接口核心层就原创 2013-07-21 22:44:36 · 4405 阅读 · 0 评论 -
TCP协议中的SO_LINGER选项
SO_LINGER选项用来设置延迟关闭的时间,等待套接字发送缓冲区中的数据发送完成。没有设置该选项时,在调用close()后,在发送完FIN后会立即进行一些清理工作并返回。如果设置了SO_LINGER选项,并且等待时间为正值,则在清理之前会等待一段时间。以调用close()主动关闭为例,在发送完FIN包后,会进入FIN_WAIT_1状态。如果没有延迟关闭(即设置SO_LINGER选项),在调用原创 2013-07-19 11:28:19 · 2280 阅读 · 0 评论 -
浅析内核中用户进程的创建
进程创建是一个非常复杂的过程,涉及到很多的技术细节,以及与内核中的很多子系统的交互等,要完整的讨论到各种情况不太可能,这里只以用户空间调用fork()创建进程为例来进行讨论。 fork()系统调用对应的内核实现为sys_fork(),sys_fork()是对do_fork()的简单封装,sys_fork()的任务是从处理器寄存器中提取由用户空间提供的信息,do_fork()负责进程的复制。f原创 2013-06-30 22:29:49 · 1991 阅读 · 0 评论 -
结合内核源码来看如何调整影响TIME_WAIT状态套接字数量的参数
这篇文件主要讨论tcp_max_tw_buckets、tcp_timestamps、tcp_tw_recycle、tcp_tw_reuse和tcp_fin_timeout参数。 测试的时候看到系统日志中不断地出现“TCP: time wait bucket table overflow”的信息。在代码中搜索了一下,看到这条日志是在tcp_time_wait()函数中输出的,输出这条日志是在局原创 2013-06-10 11:07:28 · 3639 阅读 · 0 评论 -
__do_strncpy_from_user()源码分析
在用户层发起系统调用时,有时需要向内核传递字符串。内核通常不会直接操作用户传入的字符串,而是先拷贝到内核缓冲区中。因为是用户态传入的指针,并不能保证在拷贝的过程中不会发生异常,所以内核必须保证这种异常不会影响到内核的运行。内核通常会使用copy_from_user()或者strncpy_from_user()等类似的函数来执行拷贝操作。我们这里以strncpy_from_user()(64位系统)原创 2013-05-25 10:27:37 · 2826 阅读 · 0 评论 -
进程地址空间的布局(整理)
虚拟地址空间中包含了若干区域。其分布方式是特定于体系结构的,但所有方法都有下列共同成分。 1)当前运行的二进制代码。该代码通常称之为text,所处的虚拟内存区域称之为text段。 2)程序使用的动态库的代码 3)用于保存全局变量和动态产生的数据的堆(应该还包括静态变量) 4)用于保存局部变量和实现函数/过程调用的栈。 5)环境变量和命令行参数的段 6)将文件内容映射到虚拟地原创 2013-05-11 15:08:36 · 5413 阅读 · 0 评论 -
为什么linux kernel默认的页面大小是4K,而不是4M或8M?
相信很多人在看内核内存管理部分的时候,都有这样一个疑问,为什么物理页面的大小选择4K,而不是大一些或者小一些呢?这个问题没有固定的答案,仁者见仁智者见智,每个人的关注点不一样。所以这篇文章不是说给出一个固定的答案,更多的只是一篇讨论性的文章。内核的页面大小首先跟CPU有关,不同的架构支持的页面大小也不相同,但有一个共同点,那就是肯定支持4K的页面大小。为什么处理器在设计的时候会选择4K,而原创 2013-05-10 11:58:54 · 11355 阅读 · 1 评论 -
内核中accept连接时创建socket结构错误导致的内存泄露
强烈推荐一下淘宝褚霸的这篇文章: http://blog.yufeng.info/archives/2456 注:这里我们只关心TCP套接字,所以文章中说sock结构或者socket结构的时候都只针对TCP协议。 在测试内核模块时,内核会因为内存耗尽而panic,使用crash工具查看core文件,提示的信息是"Kernel panic - not syncing: Out of原创 2013-04-26 17:06:45 · 3451 阅读 · 0 评论 -
如何在Linux kernel Makefile中添加宏定义
原文地址:http://freshpassport.blog.51cto.com/2359526/619274如何在Linux kernel Makefile中添加宏定义: CFLAGS_object.o += -DMACRO_NAME在编译object.o时定义宏MACRO_NAME,在kernel中添加自己的模块时比较有用。 另外,要想对所以将编译的文件都添加一转载 2013-04-24 11:08:25 · 5544 阅读 · 0 评论 -
SYN cookies机制下连接的建立
在正常情况下,服务器端接收到客户端发送的SYN包,会分配一个连接请求块(即request_sock结构),用于保存连接请求信息,并且发送SYN+ACK包给客户端,然后将连接请求块添加到半连接队列中。客户端接收到SYN+ACK包后,会发送ACK包对服务器端的包进行确认。服务器端收到客户端的确认后,根据保存的连接信息,构建一个新的连接,放到监听套接字的连接队列中,等待用户层accept连接。这是正常的原创 2013-10-11 16:55:44 · 8842 阅读 · 0 评论 -
《浅谈TCP协议栈》ppt分享
这个是在公司内部串讲时候的ppt,分享一下!浅谈TCP协议栈.pptx原创 2013-10-22 23:36:46 · 1974 阅读 · 0 评论 -
相同端口的UDP套接字数量过多导致软中断占用CPU利用率高的原因分析
导致出现很多相同端口的UDP套接字的原因有两点: 1)在reload的时候,调用shutdown()而不是close()来关闭UDP套接字。shutdown()是用来关闭连接的,但是文件描述符还是会存在。UDP协议并没有提供shutdown接口(参见udp_prot),所以调用shutdown()并没有真的关闭套接字,而且reload的次数太多。 2)设置了SO_REUSEAD原创 2014-03-07 18:35:41 · 5209 阅读 · 1 评论 -
/proc/net/tcp中各项参数说明
/proc/net/tcp中的内容由tcp4_seq_show()函数打印,该函数中有三种打印形式,我们这里这只列出状态是TCP_SEQ_STATE_LISTENING或TCP_SEQ_STATE_ESTABLISHED的情况,如下所示:原创 2014-03-11 18:02:54 · 20642 阅读 · 0 评论 -
源目的IP和端口都相同的连接出现的原因
线上遇到了一个比较特殊的连接,它的源目的IP和端口完全相同,复现的场景是:同一个机器上的两个模块A和B通信,A模块会向B模块的监听套接字发起连接请求,B模块重启的时候就很容易出现这样的问题。下图是在线下复现的连接情况: 这种类型的连接产生的过程类似于同时打开的情况。同时打开的情况是两个机器同时向另一个机器的已知端口发送SYN段,一个机器上发送的SYN段的目的IP和端口是另原创 2014-03-10 20:20:07 · 10917 阅读 · 1 评论 -
Linux虚拟内存系统常用参数说明
1.admin_reserve_kbytes 给有cap_sys_admin权限的用户保留的内存数量,默认值是min(free pages * 3%, 8MB)。这些内存是为了给管理员登录和杀死进程恢复系统提供足够的内存。2.block_dump 如果设置的是非零值,则会启用块I/O调试。更多的关于块I/O调试的信息可以参见Documentation/laptops/lapto原创 2014-02-19 12:28:10 · 5645 阅读 · 0 评论 -
linux kernel 2.6.32内核代码注释
看内核代码也有一段时间了,记了很多注释,分享出来。地址:http://www.kuaipan.cn/file/id_61251671069793742.htm原创 2013-06-30 07:19:30 · 5306 阅读 · 5 评论 -
如何查找Linux中一些特殊数据类型定义,比如pid_t和uid_t
刚开始学习的时候看到像pid_t、uid_t这样的类型,总是想知道它的定义在哪,究竟是什么类型。但是直接看使用这些类型的函数的头文件根本就找不到。这里把我的一些经验分享给大家,希望有所帮助。 下面以pid_t类型和getpid函数为例,getpid的定义如下: #include #include pid_t getpid(void);原创 2012-07-28 12:42:46 · 16078 阅读 · 7 评论 -
Linux CFS调度系统----周期性调度器
周期性调度器由scheduler_tick()函数实现,在每个时钟中断中都会调用该函数来更新一些统计量,并且会激活当前进程所属调度类的周期性处理接口,代码流程如下所示: 具体来说,scheduler_tick()做了以下工作: 1)更新就绪队列的实际时钟时间,不是虚拟时钟时间。 2)更新就绪队列权重数组cpu_load中的权重值 3)调用当前CPU上原创 2013-12-26 13:08:48 · 2918 阅读 · 0 评论 -
Linux CFS调度系统----进程优先级和权重
调度器的一般原理是,根据所能分配的计算能力,向系统中的每个进程提供最大的公平性。调度器分配的资源就是CPU的时间,尽量保证每个进程都获得相同的CPU时间。Linux的CFS调度系统不同于O(1)调度器,不需要时间片概念,至少不需要传统的时间片。CFS调度系统只考虑进程的等待时间,即进程在就绪队列中已经等待了多长时间。但是并非系统上的所有进程都同样重要,调度器也要保证一些重要的进程优先执行,或者要获原创 2013-12-19 14:14:38 · 5005 阅读 · 0 评论 -
epoll源码分析---sys_epoll_create()函数
eventpoll的优点就不用说了,网上的资料很多,eventpoll的使用也很广泛,特别是在Web服务器中。因为最近要用到epoll,所以好好地看了一下它的实现,把学到的一些东西做下整理,做个记录。一、sys_epoll_create() 其源码如下:SYSCALL_DEFINE1(epoll_create, int, size){ if (size <= 0)原创 2013-01-15 18:34:01 · 5345 阅读 · 1 评论 -
Linux TCP协议栈中的预分配缓存
TCP协议栈中的预分配缓存的大小由sock结构中的sk_forward_alloc成员描述,在创建套接字时该成员被初始化为0(参见sk_clone())。虽然这个成员在内核文档和《Linux内核源码剖析---TCP/IP实现中》都描述为预分配缓存的长度,但是在代码中并没有看到使用这个成员来预先分配一段内存,更多地是通过这个成员来控制TCP协议栈使用的内存。其实sk_forward_alloc更应该原创 2013-12-17 14:33:49 · 3976 阅读 · 0 评论 -
Kprobes源码分析----kprobe的处理
在探测点注册kprobe后,会在执行到探测点的指令时触发断点异常(trap 3)。kprobes在断点异常的通知链die_chain上注册了自己的处理函数,这个函数就是kprobe_exception_notify()。kprobe_exception_notify()不仅会接收到断点异常的通知,还会接收到调试异常(trap 1)和保护异常的通知。这篇文章主要围绕这个函数的处理来展开。原创 2013-11-10 09:26:10 · 2856 阅读 · 0 评论 -
Kprobes源码分析----kprobe的注册
kprobes是一个动态地收集调试和性能信息的工具,使用它几乎可以跟踪任何函数或被执行的指令。它的机制也很简单,就是将被探测的位置的指令替换为断点指令(不考虑jmp优化),断点指令被执行后会通过notifier_call_chain机制来通知kprobes,kprobes会首先调用用户指定的pre_handler接口。执行pre_handler接口后会单步执行原始的指令,如果用户也指定了post_原创 2013-11-07 13:44:30 · 3349 阅读 · 0 评论 -
LVS-DR模式配置详解
每次配置LVS时,都要重新上网去找配置方法,这些方法有些是错误的,而且大多数讲解的不是很全面,每次都要花些时间来排错,所以决定自己写一篇,记录下来,以免以后再浪费时间。LVS的安装就不说了,在linux下开发如果不会安装类似LVS这样的软件,也太说不过去了,这篇文章只记录怎样配置LVS。LVS的DR方式是最常用,因此只介绍这一种方式。 配置环境说明:系统CentOS6.2,虚拟IP(VIP)原创 2013-01-24 22:04:51 · 8009 阅读 · 2 评论 -
TIME_WAIT状态下对接收到的数据包如何处理
正常情况下主动关闭连接的一端在连接正常终止后,会进入TIME_WAIT状态,存在这个状态有以下两个原因(参考《Unix网络编程》): 1、保证TCP连接关闭的可靠性。如果最终发送的ACK丢失,被动关闭的一端会重传最终的FIN包,如果执行主动关闭的一端没有维护这个连接的状态信息,会发送RST包响应,导致连接不正常关闭。 2、允许老的重复分组在网络中消逝。假设在一个连接关闭原创 2013-03-27 11:00:40 · 6330 阅读 · 4 评论 -
linux内核模块的加载过程
前段时间为了解决内核模块无法卸载的问题,对模块的加载过程详细地学习了一番。加载模块时常用的命令是insmod和modprobe,这两个命令主要是通过系统调用sys_init_module()来完成主要的工作,用户层做的更多的是对参数的处理,以及将插入的模块加入到内存中。系统调用sys_init_module()将大部分工作委托给load_module()函数来完成,load_module()中的操原创 2013-01-30 22:44:06 · 3750 阅读 · 1 评论 -
linux下用GDB调试可加载模块
参考文章:http://cnsnap.cn.freebsd.org/doc/zh_CN.GB2312/books/developers-handbook/kerneldebug-kld.html这篇文章主要是对参考文章的简单整理,大同小异。首先,需要在编译模块时加入调试信息。两种方式,一种是编译时使用“make COPTS-g”,另一种是用“gcc -g”作为“gcc”的别名。原创 2013-01-16 10:39:49 · 7227 阅读 · 1 评论 -
内核模块中错误调用kernel_thread创建内核线程导致模块无法卸载
先介绍一下创建线程的大致流程:在模块的初始化函数中,调用netlink_kernel_create来注册自己的netlink协议,然后返回,接收netlink消息的函数为fcluster_netlink_recv,真正的初始化操作是在接收到netlink报文后才做,创建线程的操作也是在fcluster_netlink_recv中,如下图所示:调用kernel_thread的语句为:原创 2013-01-16 10:53:57 · 2547 阅读 · 0 评论 -
内核线程中获取接收到的信号
在测试开发的内核模块时,发现了一个BUG:在模块没有卸载时使用reboot命令重启系统的话,系统重启不了,查看日志发现在创建的内核线程中陷入了死循环,导致系统无法重启。检查了代码,发现产生问题的原因是当系统调用返回-EINTR(也就是被信号中断),内核线程中的循环没有退出,而是继续循环操作,这个逻辑跟业务是相符合的并没有错误。问题就在于没有检查接收到的是什么信号,如果是在系统重启时发送的信号或者执原创 2013-01-26 00:43:27 · 4363 阅读 · 1 评论 -
cpu_relax()-----对自选循环等待(spin-wait loops)操作的优化
在lock_timer_base()函数中看到在for循环操作中调用了cpu_relax(),本来以为是要让出CPU,调度其他进程运行,但是看代码之后发现完全不是这么回事。cpu_relax()中只有一条调用语句,调用的是rep_nop函数。rep_nop()函数如下:static inline void rep_nop(void){ asm volatile("rep; nop" :原创 2013-01-23 15:27:16 · 11689 阅读 · 0 评论 -
Linux编程中的错误码列表
有时可以知道错误的数值,但是如果不知道对应于那个宏定义,也很难知道这个错误描述的是什么。我平时这两种方法来确定:在内核源码中搜索和查看头文件。 在内核源码中搜索一般都可以搜到,而且使用source insight的话也很方便,不多说了。当然更多的时候还是看头文件,因为一般的错误在/usr/include/asm-generic/errno-base.h和/usr/include/asm-gener原创 2012-07-28 12:13:26 · 1951 阅读 · 0 评论 -
Linux内核的Softirq机制
第六章 Linux内核的Softirq机制 (By 詹荣开,NUDT) Copyright © 2003 by 詹荣开 E-mail:zhanrk@sohu.com Linux-2.4.0 Version 1.0.0,2003-2-14 摘要:本文主要从内核实现的角度分析了Linux 2.4.0内核的Softirq机制。本文是为那些想要了解L转载 2012-07-27 16:07:43 · 1872 阅读 · 0 评论 -
对内核源码中IS_ERR的理解
今天在看内核源码时,看到一个判断指针是否是错误指针或无效指针的函数IS_ERR(2.6.11内核,include/linux/err.h中),其源码如下: static inline long IS_ERR(const void *ptr){ return unlikely((unsigned long)ptr > (unsigned long)-1000L);}这个函原创 2012-07-26 18:41:40 · 1685 阅读 · 0 评论 -
VIM参考手册
原文地址:点击打开链接使用多个窗口和缓冲区进行编辑 *windows* *buffers*本章我们看一下操作多个窗口和缓冲区的命令。另外有些命令在操作多个窗口的时候不同于单个窗口,这些命令也会在本章被介绍。一些基本的内容在用户手册的第 7、8 两个章节里 |usr_07.txt| |usr_08.txt| 已经介转载 2012-07-27 11:44:39 · 1370 阅读 · 0 评论 -
Linux下获取本地IP地址--------getaddrinfo
获取本地IP地址的方式很多,这里使用的接口是getaddrinfo(最开始发表时,这个地方表述有错误,这个接口也不能解决主机名为localhost,获取的IP地址是127.0.0.1,但是可以通过修改/etc/hosts文件来绑定本地IP地址)。这个接口在《Unix网络编程》第一卷的11.2节有讲解,但是当时看书的时候没有深入的研究这个接口(当时可能感觉获取本地ip地址很容易),这个接口及其相关的原创 2012-07-24 15:26:10 · 15890 阅读 · 3 评论 -
Linux下获取本地IP地址--------ioctl
获取本地的局域网IP地址,个人认为最好的还是这个神器---ioctl,这个接口的功能真是非常强大,非常值得研究和学习。即使本地的主机名是localhost,使用ioctl也可以轻松地获取局域网中的IP地址,而且不需要在/etc/hosts中绑定局域网IP。使用ioctl来获取本地局域网IP地址,需要首先创建一个套接字和一个struct ifreq结构(值-结果参数),下面首先介绍struct if原创 2012-07-25 17:59:32 · 3770 阅读 · 2 评论