精华内容
下载资源
问答
  • <p>I am confused by goroutine, user thread, and kernel thread concepts <li><p>From <a href="http://golang-jp.org/doc/effective_go.html#goroutines" rel="nofollow noreferrer">effective go ...
  • Linux x86_64内核终止D状态的进程

    万次阅读 2016-11-07 21:36:32
    在上一篇文章《Linux x86内核终止D状态的进程》中,我展示了32位x86系统中如何编码杀死D进程。本文我将展示一种64位x86系统上的方法。 说实话,64位系统上做这样的事比较难的,因为你无法通过修改p->thread.ip来...
    在上一篇文章《Linux x86内核终止D状态的进程》中,我展示了32位x86系统中如何编码杀死D进程。本文我将展示一种64位x86系统上的方法。
            说实话,64位系统上做这样的事是比较难的,因为你无法通过修改p->thread.ip来到达将进程拽出死循环的目的。要想知道64位系统上到底该怎么把进程执行绪引出,我们得先看看”标准“的做法是什么。

            标准的做法就是fork时的行为,一个新进程刚刚被创建,它第一次进入运行状态之前,并不是通过switch_to切出的,为了让它”看起来像“是被切出而后被切入,就需要ret_from_fork来制造现场。问题是既然无法修改p->thread.ip,那又如何把执行绪引导到ret_from_fork里。

            答案在于,64位(这里特指x86_64)系统是在switch_to中直接通过标志位判断跳转的,其过程如下:

    1.在copy_thread中设置TIF_FORK标志

    2.在switch_to中判断TIF_FORK标志是否存在,若存在则直接跳转到ret_from_fork

    因此ret_from_fork在64位系统中是硬编码到switch_to中的,不像32位系统中那样是可以随意修改的。

            到这里,想通过修改堆栈上保存的PC寄存器来达到跳出循环的这条心也该死了。一个进程被切入,要么循着被切出之前的路径走,要么进入ret_from_fork,只有这两条路。如果循着之前的路,那还是在死循环里面,那么只能给D进程设置TIF_FORK标记,引导它进入ret_from_fork!
            然而我们并不是真的希望它return from fork,而是因为这是不得已的办法,它只能到ret_from_fork里面。接下来怎么办?
            接下来的技术涉及到inline hook,我们希望hook掉ret_from_fork这个entry!具体如何inline hook,本文不讲,不然本文又要很长很长了。本文仅仅给出ret_from_fork被hook后的样子:
    ENTRY(ret_from_fork)
            DEFAULT_FRAME
    
            LOCK ; btr $TIF_FORK,TI_flags(%r8)
    
            push kernel_eflags(%rip)
            CFI_ADJUST_CFA_OFFSET 8
            popf                                    # reset kernel eflags
            CFI_ADJUST_CFA_OFFSET -8
    
            call schedule_tail                      # rdi: 'prev' task parameter
    
            GET_THREAD_INFO(%rcx)
            
            testl $_TIF_D, TI_flags(%rcx)        # 这里判断是不是有新增的TIF_D标识,如果有,就直接do_exit
            jnz do_exit
    
            RESTORE_REST
    
    
            testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
            je   int_ret_from_sys_call
    
            testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
            jnz  int_ret_from_sys_call
    
            RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
            jmp ret_from_sys_call                   # go to the SYSRET fastpath
    
            CFI_ENDPROC
    END(ret_from_fork)

    然后,模块里非常简单的设置TIF_FORK和TIF_D即可:
    if (pid > 0) {
        for_each_process(p) {
            if (task_pid_vnr(p) == pid) {
                set_task_state(p, TASK_INTERRUPTIBLE);
                // 设置TIF_FORK,目的是执行流导入ret_from_fork
                set_tsk_thread_flag(p, TIF_FORK);
                // 设置TIF_D,目的是将执行流在hook后的ret_from_fork里进行区分
                set_tsk_thread_flag(p, TIF_D);
                wake_up_process(p);
                break;
            }
        }
    }

    和32位系统的实验方法一样,D进程将被拉出死循环,然后死掉!

            注意,用kprobe/jprobe技术进行hook事实上就是一种inline hook的应用,然而我们不方便用它来hook ret_from_fork,因为你既不能在ret_from_fork之前执行hook,也不能之后执行hook,而必须在其中间,即调用完schedule_tail之后去执行do_exit,因此,正确的做法是hook别的函数而不是hook ret_from_fork这个函数。仔细观察ret_from_fork的汇编码,就会发现在int_ret_from_sys_call,ret_from_sys_call的pre handler中进行TIF_D的判断并且执行do_exit应该是正确的做法!

            温州皮鞋,下雨进水不会胖!


    展开全文
  • 在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态。而在相应的低级别执行状态下,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动。举例:intel x86 CPU有四种...

    原文地址:https://blog.csdn.net/morixinguan/article/details/50775417

    一般现代CPU都有几种不同的指令执行级别。

    在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态。

    而在相应的低级别执行状态下,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动。

    举例:

    intel x86 CPU有四种不同的执行级别0-3,linux只使用了其中的0级和3级分别来表示内核态和用户态。

       

            我想说,对于这个知识我问过我们学校的大牛廖建文老师有关进程问题fork的时候,他跟我说过内核0级环的概念,其实也就是处于内核态。大笑大笑用上面这幅图可以表示出来。

    如何区分用户态和内核态?

    CS寄存器的最低两位表明了当前代码的特权级。

    CPU每条指令的读取都是通过CS:eip这两个寄存器:

    其中cs是代码段选择寄存器,eip是偏移量寄存器。

    上述判断由硬件完成。

    一般来说在linux中,地址空间是一个显著的标志:0xc0000000以上的地址空间只能在内核态下访问,

    0x00000000-0xbfffffff的地址空间在两种状态下都可以访问。

    注意:这里所说的地址空间是逻辑地址而不是物理地址。


    其实孟宁老师在讲解内核知识点已经把这个知识点最精华的部分提取出来了,那么到底内核中有什么样的接口是跟老师说的相关的呢?

    其实写过linux内核驱动程序的同学应该就知道,实现一个字符设备驱动,在write方法和read方法中,内核态和用户态之间的桥梁就是copy_to_user和copy_form_user这两个接口,因为孟老师说了在高执行级别下,代码可以执行特权指令,访问任意的物理地址,这种CPU执行级别就对应着内核态,而在相应的低级别执行状态下,代码的掌控范围会受到限制。只能在对应级别允许的范围内活动。其实正好说明了这个问题,程序员或者软件应用工程师在编写应用程序去控制设备驱动的时候,首先肯定是会打开相应的文件描述符,然后对相应的文件描述符进行读写,ioctl,lseek之类的操作。当在应用层编写程序即是属于用户态,在应用程序不能访问任意的硬件物理地址,所以当用户需要读取文件描述符的内的内容时,就需要调用read,当用户需要写数据进文件描述符时,就需要用write,在用户态调用这两个接口,进而就会进行系统调用,产生相应的系统调用号,然后内核会根据系统调用号找到相应的驱动程序,此时系统就处在内核态中,在驱动程序中,首先进行驱动程序初始化,然后注册,产生驱动程序最重要主设备号和次设备号。初始化的过程中由于对相应的read方法和wirte方法进行初始化,故用户态执行read操作,就会进而使CPU产生异常,然后进入内核态找到相应的read,write当然也是一样的。

    就如同下面这张图:


    当然,我的分析依然还是处于非常片面的,只能说个大概,因为操作系统在执行系统调用的过程依然是非常复杂的,但是复杂归复杂,对于这样的一个流程我们还是应当要去了解清楚。

    还有一个例子就是,假设我需要实现一个led驱动或者其它的驱动,在内核驱动中,我需要将相应的物理地址ioremap成为一个虚拟地址,当驱动调用结束后,还应当取消相应的地址映射,这其实就是在内核态进行的操作,因为在内核中,访问这些地址以虚拟地址的形式进行相应的内存分配。为了使软件访问I/O内存,必须为设备分配虚拟地址.这就是ioremap的工作。

      还有一个例子就是在用户态进行mmap操作。Linux中的内核空间到用户空间的地址映射让用户层应用可以直接访问内核地址,这就是mmap方法。

      关于这方面的知识,本人也是非常感兴趣,当然完成的对这个过程进行剖析,还需要剖析进程的创建,然后进程的调度一系列的问题,还有一个离不开的内存管理,有了内存管理那就一定存在MMU,一定需要页表的映射等等。往后若有总结,我会将知识点分享出来!大笑

    展开全文
  • ACK 报文限速是什么鬼 SystemTap 工具在 linux 内核追踪中的使用 包注入神器 scapy 的使用 RST 攻击的原理 killcx 等工具利用 RST 攻击的方式来杀掉连接的原理 接下来开始文章的内容。 scapy 实验复现现象 ...
    •  ESTABLISHED 状态的连接收到乱序包会回复什么
    • Challenge ACK 的概念
    • ACK 报文限速是什么鬼
    • SystemTap 工具在 linux 内核追踪中的使用
    • 包注入神器 scapy 的使用
    • RST 攻击的原理
    • killcx 等工具利用 RST 攻击的方式来杀掉连接的原理

    接下来开始文章的内容。

    scapy 实验复现现象

    实验步骤如下:

    在机器 A(10.211.55.10) 使用 nc 启动一个服务程序,监听 9090 端口,如下所示。

    nc -4 -l 9090

    机器 A 上同步使用 tcpdump 抓包,其中 -S 表示显示绝对序列号。

    sudo tcpdump -i any port 9090 -nn  -S

    在机器 B 使用 nc 命令连接机器 A 的 nc 服务器,输入 "hello" 。

    nc 10.211.55.10 9090

    使用 netstat 可以看到此次连接的信息。

    Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
    tcp        0      0 10.211.55.10:9090       10.211.55.20:50718      ESTABLISHED 9029/nc

    在机器 B 上使用 scapy,模拟发送 SYN 包,scapy 脚本如下所示。

    send(IP(dst="10.211.55.10")/TCP(sport=50718, dport=9090, seq=10, flags='S'))

    源端口号 sport 使用此次连接的临时端口号 50718,序列号随便写一个,这里 seq 为 10。

    执行 scapy 执行上面的代码,tcpdump 中显示的包结果如下。

    // nc 终端中 hello 请求包
    18:41:51.956735 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [P.], seq 3219267420:3219267426, ack 2848436085, win 229, options [nop,nop,TS val 1094540820 ecr 12823113], length 6
    18:41:51.956787 IP 10.211.55.10.9090 > 10.211.55.20.50718: Flags [.], ack 3219267426, win 227, options [nop,nop,TS val 12827910 ecr 1094540820], length 0
    
    // scapy 的 SYN 包
    18:44:32.373331 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0
    18:44:32.373366 IP 10.211.55.10.9090 > 10.211.55.20.50718: Flags [.], ack 3219267426, win 227, options [nop,nop,TS val 12988327 ecr 1094540820], length 0

    可以看到,对于一个 SEQ 为随意的 SYN 包,TCP 回复了正确的 ACK 包,其确认号为 3219267426。

    从 rfc793 文档中也可以看到:

    Linux 内核对于收到的乱序 SYN 报文,会回复一个携带了正确序列号和确认号的 ACK 报文。

    这个 ACK 被称之为 Challenge ACK。

    我们后面要介绍的杀掉连接工具 killcx 的原理,正是是基于这一点。

    原因分析

    为了方便说明,我们记发送 SYN 报文的一端为 A,处于 ESTABLISHED 状态接收 SYN 报文的一端为 B,B 对收到的 SYN 包回复 ACK 的原因是想让对端 A 确认之前的连接是否已经失效,以便做出一些处理。

    对于 A 而已,如果之前的连接还在,对于收到的 ACK 包,正常处理即可,不再讨论。

    如果 A 之前的此条连接已经不在了,此次 SYN 包是想发起新的连接,对于收到的 ACK 包,会立即回复一个 RST,且 RST 包的序列号就等于 ACK 包的序列号,B 收到这个合法的 RST 包以后,就会将连接释放。A 此时若想继续与 B 创建连接,则可以选择再次发送 SYN 包,重新建连,如下图所示。

    接下来我们来看内核源码的处理,

    内核源码分析

    在这之前,我们需要先了解 SystemTap 工具的使用。SystemTap 是 Linux 中非常强大的调试探针工具,类似于 java 中的 javaagent instrument,可以获取一个内核函数运行时的入参变量、返回值、调用堆栈,甚至可以直接修改变量的值。这个工具详细的使用这里不展开,感兴趣的同学可以自行 Google。

    接下来我们来使用 SystemTap 这个工具来给内核插入 probe 探针,以 3.10.0 内核为例,内核中回复的 ack 的函数在 net/ipv4/tcp_output.c 的 tcp_send_ack 中实现。我们给这个函数插入调用探针,在端口号为 9090 时打印调用堆栈。新建一个 ack_test.stp 文件,部分代码如下所示。

    %{
    #include <net/sock.h>
    #include <linux/tcp.h>
    #include <linux/skbuff.h>
    #include <net/route.h>
    %}
    
    function tcp_src_port:long(sk:long)
    {
    	return __tcp_sock_sport(sk)
    }
    function tcp_dst_port:long(sk:long)
    {
    	return __tcp_sock_dport(sk)
    }
    function tcp_src_addr:long(sk:long)
    {
    	return ntohl(__ip_sock_saddr(sk))
    }
    function tcp_dst_addr:long(sk:long)
    {
    	return ntohl(__ip_sock_daddr(sk))
    }
    function str_addr:string(addr, port) {
            return sprintf("%d.%d.%d.%d:%d",
                           (addr & 0xff000000) >> 24,
                           (addr & 0x00ff0000) >> 16,
                           (addr & 0x0000ff00) >> 8,
                           (addr & 0x000000ff),
                           port
                    )
    }
    
    probe kernel.function("tcp_send_ack@net/ipv4/tcp_output.c")
    {
           src_addr = tcp_src_addr($sk);
           src_port = tcp_src_port($sk);
           dst_addr = tcp_dst_addr($sk);
           dst_port = tcp_dst_port($sk);
           if (dst_port == 9090 || src_port == 9090)
           {
                  printf("send ack : %s:->%s\n",
                         str_addr(src_addr, src_port),
                         str_addr(dst_addr, dst_port));
                  print_backtrace();
           }
    }

    使用 stap 命令执行上面的脚本

    sudo stap -g ack_test.stp
    

    再次使用 scapy 发送一个 syn 包,内核同样会回复 ACK,此时 stap 输出结果如下。

    send ack : 10.211.55.10:9090:->10.211.55.20:50718
     0xffffffff815d0940 : tcp_send_ack+0x0/0x170 [kernel]
     0xffffffff815cb1d2 : tcp_validate_incoming+0x212/0x2d0 [kernel]
     0xffffffff815cb44d : tcp_rcv_established+0x1bd/0x760 [kernel]
     0xffffffff815d5f8a : tcp_v4_do_rcv+0x10a/0x340 [kernel]
     0xffffffff815d76d9 : tcp_v4_rcv+0x799/0x9a0 [kernel]
     0xffffffff815b1094 : ip_local_deliver_finish+0xb4/0x1f0 [kernel]
     0xffffffff815b1379 : ip_local_deliver+0x59/0xd0 [kernel]
     0xffffffff815b0d1a : ip_rcv_finish+0x8a/0x350 [kernel]
     0xffffffff815b16a6 : ip_rcv+0x2b6/0x410 [kernel]

    可以看到这个 ACK 经过了下面这些函数调用。

    tcp_v4_rcv
      -> tcp_v4_do_rcv
        -> tcp_rcv_established
          -> tcp_validate_incoming
            -> tcp_send_ack

    tcp_validate_incoming 函数精简后的部分代码如下所示。

    static bool tcp_validate_incoming(struct sock *sk, struct sk_buff *skb,
    				  const struct tcphdr *th)
    {	
    	// seq 不在窗口内
    	/* Step 1: check sequence number */
    	if (!tcp_sequence(tp, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq)) {
    		// RST 标记没有设置
    		if (!th->rst) {
    			if (th->syn)
    				goto syn_challenge;
    		}
    		goto discard;
    	}
    	
    	/* step 4: Check for a SYN。 RFC 5961 4.2 : Send a challenge ack */
    	if (th->syn) {
    syn_challenge: // 处理 SYN Challenge 的情况
    		tcp_send_challenge_ack(sk, skb); // 
    		goto discard;
    	}

    tcp_send_challenge_ack 函数真正调用了 tcp_send_ack 函数。 这里的注释提到了 RFC 5961 4.2,说的正是 Challenge ACK 相关的内容。

    如果攻击者疯狂发送假的乱序包,接收端也跟着回复 Challenge ACK,会耗费大量的 CPU 和带宽资源。于是 RFC 5961 提出了 ACK Throttling 方案,限制了每秒钟发送 Challenge ACK 报文的数量,这个值由 net.ipv4.tcp_challenge_ack_limit 系统变量决定,默认值是 1000,也就是 1s 内最多允许 1000 个 Challenge ACK 报文。

    接下来使用 sysctl 将这个值改小为 1,如下所示。

    sudo sysctl -w net.ipv4.tcp_challenge_ack_limit="1"

    这样理论上在一秒内多次发送一个 Challenge ACK 包,接下来使用 scapy 在短时间内发送 5 次 SYN 包,看看内核是否只会回复一个 ACK 包,scapy 的脚本如下所示。

    send(IP(dst="10.211.55.10")/TCP(sport=50718,dport=9090,seq=10,flags='S'), loop=0, count=5)

    tcpdump 抓包结果如下。

    03:40:30.970682 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0
    03:40:30.970771 IP 10.211.55.10.9090 > 10.211.55.20.50718: Flags [.], ack 3219267426, win 227, options [nop,nop,TS val 45146923 ecr 1094540820], length 0
    03:40:30.974889 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0
    03:40:30.975004 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0
    03:40:30.978643 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0
    03:40:30.981987 IP 10.211.55.20.50718 > 10.211.55.10.9090: Flags [S], seq 10, win 8192, length 0

    可以看到确实是只对第一个 SYN 包回复了一个 ACK 包,其它的四个 SYN 都没有回复 ACK。

    RST 攻击

    RST 攻击也称为伪造 TCP 重置报文攻击,通过伪造 RST 报文来关闭掉一个正常的连接。

    源 IP 地址伪造非常容易,不容易被伪造的是序列号,RST 攻击最重要的一点就是构造的包的序列号要落在对方的滑动窗口内,否则这个 RST 包会被忽略掉,达不到攻击的效果。

    +0 < S 0:0(0) win 32792 <mss 1460> 
    +0 > S. 0:0(0) ack 1 <...>
    +.1 < . 1:1(0) ack 1 win 65535 
    +0 accept(3, ..., ...) = 4
    
    // 不在窗口内的 RST
    +.010 < R. 29202:29202(0) ack 1 win 65535
    
    // 如果上面的 RST 包落在窗口内,连接会被重置,下面的写入不会成功
    +.010 write(4, ..., 1000) = 1000 
    
    // 断言服务端会发出下面的数据包
    +0 > P. 1:1001(1000) ack 1 <...>

    抓包文件中的第 5 个包可以看到,write 调用成功,1000 字节发送成功,write 调用并没有收到 RST 包的影响。

    下面来介绍两个工具,利用 RST 攻击的方式来杀掉一条连接。

    工具一:tcpkill 工具使用及原理介绍

    Centos 下安装 tcpkill 命令步骤如下

    yum install epel-release -y
    yum install dsniff -y

    实验步骤: 1、机器 c2(10.211.55.10) 启动 nc 命令监听 8080 端口,充当服务器端,记为 B

    nc -l 8080

    2、机器 c2 启动 tcpdump 抓包

    sudo tcpdump -i any port 8080 -nn -U -vvv -w test.pcap

    3、本地机器终端(10.211.55.2,记为 A)使用 nc 与 B 的 8080 端口建立 TCP 连接

    nc c2 8080

    在服务端 B 机器上可以看到这条 TCP 连接

    netstat -nat | grep -i 8080
    tcp        0      0 10.211.55.10:8080       10.211.55.2:60086       ESTABLISHED

    4、启动 tcpkill

    sudo tcpkill -i eth0 port 8080

    注意这个时候 tcp 连接依旧安然无恙,并没有被杀掉。

    5、在本地机器终端 nc 命令行中随便输入一点什么,这里输入hello,发现这时服务端和客户端的 nc 进程已经退出了

    可以看到,tcpkill 假冒了 A 和 B 的 IP发送了 RST 包给通信的双方,那问题来了,伪造 ip 很简单,它是怎么知道当前会话的序列号的呢?

    tcpkill 的原理跟 tcpdump 差不多,会通过 libpcap 库抓取符合条件的包。 因此只有有数据传输的 tcp 连接它才可以拿到当前会话的序列号,通过这个序列号伪造 IP 发送符合条件的 RST 包。

    原理如下图所示

    可以看到 tcpkill 对每个端发送了 3 个RST 包,这是因为在高速数据传输的连接上,根据当前抓的包计算的序列号可能已经不再 TCP 连接的窗口内了,这种情况下 RST 包会被忽略,因此默认情况下 tcpkill 未雨绸缪往后计算了几个序列号。还可以指定参数-n指定更多的 RST 包,比如tcpkill -9

    根据上面的分析 tcpkill 的局限还是很明显的,无法杀掉一条僵死连接,下面我们介绍一个新的工具 killcx,看看它是如何来处理这种情况的。

    工具二:killcx

    killcx 是一个用 perl 写的在 linux 下可以关闭 TCP 连接的脚本,无论 TCP 连接处于什么状态。

    1. killcx安装步骤
    2. 依赖包 安装出错解决①
    3. 依赖包 安装出错解决②

    下面来做一下实验,实验的前几步骤跟第一个例子中一模一样

    1、机器 c2(10.211.55.10) 启动 nc 命令监听 8080 端口,充当服务器端,记为 B

    nc -l 8080

    2、机器 c2 启动 tcpdump 抓包

    sudo tcpdump -i any port 8080 -nn -U -vvv -w test.pcap

    3、本地机器终端(10.211.55.2,记为 A)使用 nc 与 B 的 8080 端口建立 TCP 连接

    nc c2 8080

    在服务端 B 机器上可以看到这条 TCP 连接

    netstat -nat | grep -i 8080
    tcp        0      0 10.211.55.10:8080       10.211.55.2:61632       ESTABLISHED

    4、客户端 A nc 命令行随便输入什么,这一步也完全可以省略,这里输入"hello\n"

    5、执行 killcx 命令,注意 killcx 是在步骤 4 之后执行的

    sudo ./killcx 10.211.55.2:61632

    可以看到服务端和客户端的 nc 进程已经退出了。

    抓包的结果如下

    前 5 个包都很正常,三次握手加上一次数据传输,有趣的事情从第 6 个包开始

    • 第 6 个包是 killcx 伪造 IP 向服务端 B 发送的一个 SYN 包
    • 第 7 个包是服务端 B 回复的 ACK 包,里面包含的 SEQ 和 ACK 号
    • 第 8 个包是 killcx 伪造 IP 向服务端 B 发送的 RST 包
    • 第 9 个包是 killcx 伪造 IP 向客户端 A 发送的 RST 包

    整个过程如下图所示

    小结

    这篇文章介绍了为什么 ESTABLISHED 状态连接的需要对 SYN 包做出响应,Challenge ACK 是什么,使用 scapy 复现了现象,演示了 SystemTap 内核探针调试工具的使用,最后通过修改系统变量复现了 ACK 限速。

    文章的最后介绍了杀掉 TCP 连接的两个工具 tcpkill 和 killcx:

    • tcpkill 采用了比较保守的方式,抓取流量等有新包到来的时候,获取 SEQ/ACK 号,这种方式只能杀掉有数据传输的连接
    • killcx 采用了更加主动的方式,主动发送 SYN 包获取 SEQ/ACK 号,这种方式活跃和非活跃的连接都可以杀掉
    展开全文
  • 答: usb的链接电源管理(Link Power Management),这一个与usb硬件相关的能力,主机就能自动把设备设置成低功耗状态 转载于:https://www.cnblogs.com/dakewei/p/10567024.html...

    答: 是usb的链接电源管理(Link Power Management),这是一个与usb硬件相关的能力,主机就能自动把设备设置成低功耗状态

    转载于:https://www.cnblogs.com/dakewei/p/10567024.html

    展开全文
  • 各种文章和书籍里说的都服务端在接收到客户端的SYN报文后就进入SYN_RECV状态,然而当我看内核源码时,发现却不是这样的。连接在第一次握手后还是保持LISTEN状态,只是请求被放入了半连接状态。等到第三次握手后,...
  • 41.内核链表状态机多线程编译器

    千次阅读 2016-09-29 16:29:32
    41.1.linux内核链表 41.2.什么是状态机 41.3.多线程简介 41.4.编程工作的演进史 41.5.程序员编译器CPU之间的关系 41.6.像编译器一样思考吧
  • 内核态:当一个任务(进程)执行系统调用而陷入内核代码中执行时,我们就称进程处于内核状态,这时cpu可以访问计算机的任何资源。 用户态变为内核态: a. 系统调用 这用户态进程主动要求切换到内核态的一种方式,...
  • 进程就是出于执行期的程序,但进程并不仅仅局限于一段可以执行的代码,通常还包括其他资源,比如打开的文件,挂起的信号,内核内部数据,处理器状态,存放全局的数据段等 实际上,内核就是正在执行的程序代码的实时...
  • 1、什么是竞争状态,之前在应用编程的学习中已经提到过。 竞争状态就是在多进程环境下,多个进程同时抢占系统资源(内存、CPU、文件IO),竞争状态对OS来说很危险的,此时OS如果没处理好就会造成意想不到的结果。...
  • 摘抄之《linux内核注释》的一部分: Linux大部分都内核的 操作系统内核可能内核,也可能内核(后者有时称之为宏内核Macrokernel)。按照类似封装的形式,这些术语定义如下: l 微内核(Microkernel ...
  • 一、 什么是内核对象?  我们知道进程、线程、文件、互斥、信号量这些都操作系统级别的资源。我们在使用这些资源时,实际上都由操作系统进行创建和管理的。操作系统为了管理这些资 源,会在其内部创建一个数据...
  • 1、用户态和内核态的区别? 明白这两个概念之前,我们得...在用户空间下执行,我们把此时运行得程序的这种状态成为用户态,而当这段程序执行在内核的空间执行时,这种状态称为内核态。 当一个任务(进程)执行系统...
  • SElinux什么是SElinux?SElinux的开启关闭以及状态查看实验环境设定SElinux的安全上下文1. 查看 什么是SElinux? SELinux:Security Enhanced Linux Linux内核子系统的一个健壮的强制控制访问Mandatory Access ...
  • linux内核概述

    2020-03-15 21:24:21
    在理解linux内核之前,首先要知道什么是用户态,什么是内核态,什么是用户进程,什么是内核进程 用户进程:我们编写的程序都属于用户进程 内核进程:以内核态运行在内核地址空间,不与用户直接交互,不需要终端...
  • Linux内核编译

    2017-07-12 11:24:06
     > 编译内核的目的是什么?重新编译内核有什么好处? 编译内核的目的主要是改变内核的默认选项,比如内核原来不支持某硬件,原因是内核的相应选项默认状态是disactivated,需要改变。 当然,也有人把新版的linux装在...
  • Linux内核学习

    2019-03-11 16:26:17
    Linux内核学习基础内核简介内核源代码linux内核配置与编译3.1 定制linux...内核空间与用户空间程序执行的两种不同状态,通过系统调用和硬件中断能够完成从用户空间到内核空间的转移。 那么Linux的内核由哪些构成...
  • 内核运行环境

    2021-05-06 08:53:13
    用户进程call内核系统调用,或者内核系统调用嵌套call其它系统调用、内核扩展、内核驱动大部分所处的运行状态process environment。这个状态与用户user space的程序没什么大区别,只有所能访问的数据和函数不同...
  • 内核空间和用户空间程序执行的两种不同的状态,Linux对自身软件系统进行了划分,一部分核心的软件独立于普通的软件,拥有特权级别,可以訪问平台的全部硬件和资源,称为“内核空间”。而普通的软件执行在“用户...
  • 了解微内核

    千次阅读 2019-06-27 12:03:12
    收集了一些内容,帮助自己理解什么是内核。 术语 微内核(Microkernel) 在微内核中,大部分内核都作为单独的进程在特权状态下运行,他们通过消息传递进行通讯。在典型情况下,每个概念模块都有一个进程。因此...
  • 这种情况比较常见,一些爬虫服务器或者WEB服务器(如果网管在安装的时候没有做内核参数优化的话)上经常会遇到这个问题,这个问题怎么产生的呢? 值得一说的,对于基于TCP的HTTP协议,关闭TCP连接的Server端,...
  • 今天在公司看linux driver,相关,上午一直不想看代码,可能昨天看的太头痛,一直不想看,所以打算看会书,不如设计模式啥的,看了一个状态机的模式,听说上个公司的主板的就是用的状态机。看了一下,就是根据当前...
  • linux内核简介

    2017-12-04 18:46:57
    ②为什么要将linux系统划分为内核空间和用户空间? 主要为了保护内核代码不被普通用户程序给搞死,本质因为两者权限不同,运行时访问的寄存器不同,主要为了保护内核代码的正常运行。 ③如何进行linux...
  • ps aux命令显示的状态列中的 D 不可中断 Uninterruptible sleep (usually IO) R 正在运行,或在队列中的进程 S 处于休眠状态 < 高优先级 ...W 进入内存交换(从内核2.6开始无效) X 死掉的进程 UID.
  • 上下文切换的开销互斥锁与自旋锁为什么线程切换会导致用户态与内核台的切换? 什么是上下文切换?上下文切换的时机? CPU通过分配时间片来执行任务,当一个任务的时间片用完,就会切换到另一个任务。在切换之前会...
  • 普通线程和内核线程

    2018-03-08 10:28:00
    Linux内核线程kernel thread详解 内核线程 为什么需要内核线程 Linux内核可以看作一个服务进程(管理软...内核线程的调度由内核负责,一个内核线程处于阻塞状态时不影响其他的内核线程,因为其调度的基本单位。 ...
  • 内核同步

    2011-06-02 18:40:00
       一、什么是同步? 临界区   访问和操作共享数据的代码段。   必须被原子的访问。   在执行期间不可被打断。竞争状态   两个或者多个内核任务处于同一个临界区...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,621
精华内容 648
关键字:

内核是什么状态