V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
smallpython
V2EX  ›  程序员

程序中监听的含义?

  •  
  •   smallpython · 2019-09-11 20:18:27 +08:00 · 7272 次点击
    这是一个创建于 1929 天前的主题,其中的信息可能已经有所发展或是发生改变。
    是不是就是说死循环去访问一个资源?

    比如监听端口

    就是一个死循环的程序去检查这个端口有没有数据被传输进来?

    如果是的话,那么每次检查的间隔时间一般都设置为多久呢?
    47 条回复    2019-09-17 11:24:03 +08:00
    soulzz
        1
    soulzz  
       2019-09-11 20:21:22 +08:00
    建议了解下 nio
    xeaglex
        2
    xeaglex  
       2019-09-11 20:43:37 +08:00   ❤️ 3
    监听无非就两大类:主动轮询,或者被动通知。

    轮询就是像你说的,疯狂检查。通知就比如现在常说的异步机制。
    zxle
        3
    zxle  
       2019-09-11 20:45:39 +08:00   ❤️ 1
    lz 说的这种方式一般属于操作系统层面干的活儿
    seeker
        4
    seeker  
       2019-09-11 20:46:47 +08:00
    监听是啥含义最好看看是啥场景,可能不好概括。
    如果你说的是 linux c 语言 socket 编程,那么是先 bind ip 端口,然后死循环 accept,没有间隔时间,因为 accept 函数是阻塞的。
    高级语言 /框架可能用 listen 而不是用 bind 最为函数 /方法名,做的事情很可能有区别。不过底层的话,应该差不多。
    Fishdrowned
        5
    Fishdrowned  
       2019-09-11 21:08:30 +08:00   ❤️ 1
    没错,最终需要有人在那里死循环
    wwbfred
        6
    wwbfred  
       2019-09-11 21:18:23 +08:00
    个人理解的监听就是轮询.
    无论上层表现成什么方便高效的方式,底层都是轮询.
    只是不同的轮询方式效率不同.
    如果有误还请指正~
    Buges
        7
    Buges  
       2019-09-11 21:21:46 +08:00 via Android
    应该不能说是死循环,而是“等待”(也就是阻塞)
    Fishdrowned
        8
    Fishdrowned  
       2019-09-11 21:22:57 +08:00   ❤️ 2
    监听端口的话估计是这样:
    网卡收到报文 -> 发起硬件中断 -> CPU 停下来处理这个中断 -> OS 中断处理 -> 应用程序

    这样看起来不清楚 OS 是否需要死循环,或许不需要
    Fishdrowned
        9
    Fishdrowned  
       2019-09-11 21:23:48 +08:00
    不过 CPU 就是在无时无刻地死循环,这个是跑不了的
    billlee
        10
    billlee  
       2019-09-11 21:34:11 +08:00
    @Fishdrowned #9 CPU 明明可以 halt 的
    lilydjwg
        11
    lilydjwg  
       2019-09-11 21:38:39 +08:00   ❤️ 1
    @Fishdrowned #9 不对。网络处理有两种方式:轮询和中断。通用计算机中,通常操作系统会通过中断的方式来获知有新数据到达。

    CPU 没事干了怎么办?降频省电啊!一直没事干怎么办?电力紧张的话(比如移动设备),可以休眠啊。

    至于用户态的监听( listen )。呃,它就是设置一下连接的状态而已……用户态程序要获知新数据的到达,需要使用阻塞调用( accept )、I/O 复用接口( epoll / poll / select )、异步 I/O 等方案。
    lilydjwg
        12
    lilydjwg  
       2019-09-11 21:43:19 +08:00   ❤️ 3
    @seeker #4 你没分清楚 bind 和 listen 是干什么的。bind 是绑定本地地址。listen 是设置 TCP / UNIX 套接字的状态,好让内核能够相应的处理。

    正常工作的网络程序,也不是写个死循环 accept 就完事了。阻塞方案的方案,为实际处理事务需要通过子进程 / 线程来处理连接。调用 accept 的线程需要立即重新 accept 以等待下一个连接。不要写成我学编程的那样,不能同时处理多个连接……

    accept 是阻塞的这说法也不对。accept 是否阻塞,取决于套接字是否设置了 O_NONBLOCK 标志。
    seeker
        13
    seeker  
       2019-09-11 22:28:38 +08:00
    @lilydjwg 谢谢指正。
    starsriver
        14
    starsriver  
       2019-09-12 06:50:47 +08:00 via Android
    如果你了解硬件设备,你就会知道看门狗而不会来问这么蠢的问题。

    虽然现代计算机端口属于软件领域,但是和硬件差不多也有看门狗,不可能死循环轮寻,win10 的程序无响应了解一下?其实主要是基于任务调度,os 的触发器,就是别人说的中断。每个任务,进程,线程都有自己的编号 pid,而 cpu 每时每刻都会产生随即数来决定该为哪个服务分配资源,就行隔离,这部分基于硬件。端口也可以看作一个固定的分配号,当对应编号及缓存地址存在数据缓存或者出现头数据,触发器会开始工作,向 cpu 请求处理,处理完后数据被寄存到内存里,当前任务完成并通知其他任务继续进行
    mikulch
        15
    mikulch  
       2019-09-12 06:53:53 +08:00 via iPhone
    挺感兴趣这个话题的,希望有人能够通俗易懂的讲清楚。
    jedihy
        16
    jedihy  
       2019-09-12 07:06:38 +08:00
    OS 不会死循环的。

    Windows:
    网络 IO 都是 INT->ISR->Queue DPC ==> NDIS DPC -> LWF chain -> TCPIP (-> AFD -> Winsock1)
    xuxuzhaozhao
        17
    xuxuzhaozhao  
       2019-09-12 07:22:01 +08:00 via iPhone
    @starsriver 你打娘胎生下来就会???这个弱智那个弱智,你才最弱智。
    smallpython
        18
    smallpython  
    OP
       2019-09-12 09:51:44 +08:00
    @Fishdrowned 明白了,程序里设置的一旦触发了什么事件就去做什么事的这种逻辑.是利用了 cpu 是在无限死循环的特征.因为如果 cpu 不循环的话,那么它就停止了.
    既然 cpu 是在死循环, 那么操作系统就可以利用这个循环来实现如上所述的"触发"这个动词的效果,就可以实现通知的功能.
    就好像我并没有主动监听小明的声音,但是只要小明说话了,我就可以接受到小明的声音,这是因为我的大脑本身是在监听外部的所有信息,所以我的耳朵就不需要主动去监听小明的声音,就可以实现小明的声音触发我的动作这种效果.
    可以这样理解吗?
    smallpython
        19
    smallpython  
    OP
       2019-09-12 10:00:07 +08:00
    @lilydjwg 可是当中断的时候, 程序又是怎么知道它什么时候该继续呢?
    我的理解还是因为它轮询的判断了某一个条件, 然后才能知道是不是该继续了.
    表述可能有点拟人化,但是我觉得这个道理应该是成立的.

    就好像单核的多进程是 CPU 快速切换的假象,而不是真的有多个进程
    我想知道所谓的中断,在最底层的实现,是不是也得有一个死循环的判断逻辑
    jworg
        20
    jworg  
       2019-09-12 10:01:47 +08:00
    @smallpython 这里的部分回答应该能解释部分吧 https://www.zhihu.com/question/21440586
    guolaopi
        21
    guolaopi  
       2019-09-12 10:22:29 +08:00
    @smallpython #18
    em.....也不知道我是不是理解有偏差。但是我觉得不能是单纯简单的“CPU 死循环”,可以写个程序把所有端口都监听起来看一下 CPU 的变化。。。
    smallpython
        22
    smallpython  
    OP
       2019-09-12 10:31:41 +08:00
    @jworg 还是知乎大神多啊
    lilydjwg
        23
    lilydjwg  
       2019-09-12 11:29:41 +08:00
    @smallpython #19 「中断」是一个术语。CPU 工作的时候,网卡过来有事打断了 CPU,这就叫作中断。CPU 这时候根据中断向量表,找到对应于网卡中断的处理程序,然后 CPU 就知道有网络数据过来了。

    只有在很繁忙的设备上才会使用轮询去处理网络数据。

    当然,网卡是一直处于准备好接收数据的状态的。
    lilydjwg
        24
    lilydjwg  
       2019-09-12 11:35:04 +08:00   ❤️ 2
    @starsriver #14 你觉得你自己不蠢,可你说的也没几个对的。

    不可能死循环轮寻 => 处理大流量的设备上是可能的,因为几乎每次轮询都有数据,效率比中断高不少
    os 的触发器,就是别人说的中断 => 这里讨论的是硬件中断
    每时每刻都会产生随即数来决定该为哪个服务分配资源 => 产生随机数挺累的,CPU 怎么可能一直去做,还干不干活了?任务调度是有算法的,一般使用带优先级的队列或者位图之类的东西,并不会使用缓慢的随机数
    当对应编号及缓存地址存在数据缓存或者出现头数据,触发器会开始工作 => 并没有一个叫「触发器」的硬件会帮忙 CPU 做这部分处理
    处理完后数据被寄存到内存里 => CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了
    lilydjwg
        25
    lilydjwg  
       2019-09-12 11:38:04 +08:00
    @guolaopi #21 这个……内存的变化应该更明显。
    starsriver
        26
    starsriver  
       2019-09-12 16:53:28 +08:00 via Android
    @lilydjwg 大概解释一下而已,而且这种东西软件为主,我也就是简单说说,毕竟不是计科出来的,我就是个修电表的。。关于网卡数据和随机数,访问 1037u.starsriver.net:1080 (家里放着的工控机)定位到 entropy 和 softnet 看一下关系两者就清楚了。

    解释并没有错,只是在于看这段话的人是谁了。毕竟知识方向不一样,用不着相互批判。。。

    科班出身?

    硬件部分对于网络数据传输,也就只管二进制转模信号了,端口回来数据具体是个啥,怎么分配还是要软件来干,至于任务调度还是轮寻还是数据的处理。过程讲那么细都可以教科书了。关于网络系统有一本很厚的书,没看过。

    cpu 是通电一直在工作的,只不过没有数据处理的时候晶震会慢下来,也就省电了。

    现代网卡好象有 16k * 512 还是多大的缓存区了,cpu 存储数据的压力不大,压力大的是硬盘。
    如果没记错,所有的软件监听端口都直接依赖 os 的底层,那个库的源码。。。非常有硬件思维。明年我的课题估计就是拿 fpga 实现一下。。套接字都是已经编码好的,都是端口绑定之后的事情了,os 在这之前就会把数据分好。要真的搞清楚端口监听和绑定的细节就很有意思了,估计要触法 ip ( Intellectual Property )墙,这部分已经不太属于软件方向了。

    随机数是硬件实现的,有一个周期,cpu 只是读取一下而已。我记得在 linux 上对随机数在随机。。这种计算量对如今的设备,占用率不到万分之一。

    南桥芯片提供给 cpu 的大部分外设任务调度,包括网卡的数据通信,以前单片机用的好象是 8 什么什么集成的可编程模块。。忘了,最基本的中断就是触发和比较,这个触发器指数字电路触发器。

    硬件中断对高级语言写的软件层面作用已经不是很明显了,硬件时时刻刻在中断,一般的 pc 机一秒大概几百次到上万次。把硬件中断比作被针扎会疼,软中断就象是你看到数学题要想公式一样很复杂了,一般 os 层面的说的是软中断,总数差不多是硬件中断的五分之一。
    lilydjwg
        27
    lilydjwg  
       2019-09-12 17:08:49 +08:00
    @starsriver #26

    > 硬件部分对于网络数据传输,也就只管二进制转模信号了,端口回来数据具体是个啥,怎么分配还是要软件来干,

    是啊。剩下的都是网卡固件处理,然后转交 CPU 由 OS 继续处理。端口号都是 OS 的网络栈处理的。硬件要是干这个,那得把整个 TCP/IP 都给实现了……(感觉路由器都不想这么干吧)

    > 关于网络系统有一本很厚的书,没看过。

    那书里涉及到的东西太多了,远不止怎么收发数据这么简单。

    > 随机数是硬件实现的,有一个周期,cpu 只是读取一下而已

    不是所有设备上都有硬件随机数发生器的。

    > 我记得在 linux 上对随机数在随机。。这种计算量对如今的设备,占用率不到万分之一。

    你 cat /dev/urandom > /dev/null 试试?

    > 硬件中断对高级语言写的软件层面作用已经不是很明显了

    不写 OS 层的软件,谁接触得到硬件中断呀。OS 可不放心用户态的程序乱搞中断。

    软件中断我没怎么了解过,刚看了一下维基百科。原来访存违例和调试啥的都是软件中断实现的。所以,软件中断也不是用户态进程能够直接接触到的。

    我对硬件部分不太了解,因为我是软件工程师嘛。
    pussy2019
        28
    pussy2019  
       2019-09-12 17:54:21 +08:00
    @starsriver 虽然我不太懂,但丝毫不影响我喷你,你就是个蠢货,知道点皮毛就不知道怎么得瑟了,你要上天啊
    starsriver
        29
    starsriver  
       2019-09-12 18:00:27 +08:00 via Android   ❤️ 2
    @pussy2019 虫子总是到处飞?
    zlyang
        30
    zlyang  
       2019-09-12 18:27:43 +08:00
    说是 “监听” 不如说是 “记录”,底层接收(轮询亦或中断)网卡芯片传送过来的数据投递到网络子系统,网络子系统内部会检索有无 “目的端口” 这一记录项,然后再通过记录项对应的参数传递到对应的应用中,当然此时应用可能在轮询也可能处于阻塞中。
    dinjufen
        31
    dinjufen  
       2019-09-12 18:35:06 +08:00
    希望有大佬来详细解读一下
    zivyou
        32
    zivyou  
       2019-09-12 18:36:37 +08:00
    硬件中断,epoll 了解一下
    annielong
        33
    annielong  
       2019-09-12 18:44:30 +08:00
    问的是程序中的监听,不是系统的
    ylrshui
        34
    ylrshui  
       2019-09-12 19:37:17 +08:00 via iPhone
    监听端口,端口分为硬件端口和软件上的端口

    硬件端口一直在接收数据(电平一直在变化),能不能被处理就看你的程序是不是在正确的时刻运行处理程序,在没有缓存的硬件结构里,数据到达时没有处理,那就丢了

    网卡(一般)并不会区分收到的数据来自哪个应用程序和应该给哪个程序,它收到数据(包括预先定义好的所谓的端口号在硬件来看也只是数据),交给驱动软件处理,提取数据里的端口号(软件端口),再交给其对应的上层软件处理

    至于上层软件能不能及时正确处理,可以轮询,也可以在硬件上设个触发器,让处理器在时间到或有对应事件发生时,让它及时处理,至于触发器,有多个,有优先级,由程序设定,触发时也能告诉处理器从哪段代码开始执行
    no1xsyzy
        35
    no1xsyzy  
       2019-09-12 19:47:56 +08:00
    no1xsyzy
        36
    no1xsyzy  
       2019-09-12 20:15:36 +08:00
    @starsriver #26
    > 随机数是硬件实现的,有一个周期,cpu 只是读取一下而已。

    请看 http://1037u.starsriver.net:1080/#menu_system_submenu_entropy;help=true (你自家放的工控机?)

    > Ideally a system with high entropy demands should have a hardware device for that purpose (TPM is one such device).

    注意关键词: "Ideally", "with high entropy demands", "should"

    ——

    @lilydjwg #27

    > 你 cat /dev/urandom > /dev/null 试试?

    这不能证明什么,你 yes > /dev/null 试试?
    no1xsyzy
        37
    no1xsyzy  
       2019-09-12 20:18:20 +08:00
    @lilydjwg
    > 原来访存违例和调试啥的都是软件中断实现的
    > 软件中断也不是用户态进程能够直接接触到的
    调试器( gdb )不是用户态程序?
    reus
        38
    reus  
       2019-09-12 20:21:43 +08:00
    思而不学
    lilydjwg
        39
    lilydjwg  
       2019-09-12 20:22:02 +08:00
    @no1xsyzy #36 哦,我忘记说中间插入个 pv 看数据量了。你可以对比一下 /dev/urandom 和 yes 的生成速率。
    @no1xsyzy #37 但是 gdb 是调用内核提供的 API ( ptrace )的呀,是间接的呢。
    lilydjwg
        40
    lilydjwg  
       2019-09-12 20:24:45 +08:00
    no1xsyzy
        41
    no1xsyzy  
       2019-09-12 20:41:29 +08:00
    @lilydjwg #24
    > CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了
    你看没看新闻…… Intel 因为让网卡能够直接访问缓存导致了漏洞
    所以不一定进内存
    baixiangcpp
        42
    baixiangcpp  
       2019-09-12 20:53:37 +08:00
    这个算不算读书读的不多,想的太多(无恶意
    okwork
        43
    okwork  
       2019-09-12 21:00:00 +08:00 via Android
    网卡接收的信号,和敲击键盘的信号本质都是一样电信号变化,监听的优先级看系统逻辑。比如可以通过网络远程开机、也可以通过键盘密码开机,感觉应该是一个等级的监听。
    no1xsyzy
        44
    no1xsyzy  
       2019-09-12 21:38:20 +08:00
    @lilydjwg 其实我就是想提醒你加 pv

    慢点,难道不是 “gdb 是直接调用 ptrace 的,所以是直接使用接触软中断” 吗?
    ptrace 不就是软中断入口吗?不然直接插 x86 的被调指令?那是硬中断……
    jedihy
        45
    jedihy  
       2019-09-13 03:49:12 +08:00
    其实这个问题本质上是在问 kernel 如何通知 usermode app 事件的完成。

    以 Windows 为例:

    那这个实际上是有轮询的,但不是简单的轮询,是一个很复杂的,由 kernel thread scheduler 参与的等待过程。

    kernel 通知 usermode app 的情况,app 一定 pending 在 KeWaitForSingleObject,等待 kernel return。

    ( callstack: WaitForSingleObject->NtWaitForSingleObject->KeWaitForSingleObject )

    简单的说,在这个等待过程开始时,kernel 会设置 thread 的 scheduling state 为 waiting,然后将此 thread 放入一个 waiting list,当你 singal 一个 event 的时候,kernel 会在这个 list 中找出这个 thread,然后把它移出,然后 KeWaitForSingleObject 返回。这个时候你就知道你等待的事件被 signal 了。

    Linux 不太清楚,但现代 OS 设计大致都应该如此。Busy loop 会直接跑满一个 logical processor,所以不会有 OS 这样设计的。
    b00tyhunt3r
        46
    b00tyhunt3r  
       2019-09-13 14:04:53 +08:00 via iPhone
    @smallpython csapp 第八章
    smallpython
        47
    smallpython  
    OP
       2019-09-17 11:24:03 +08:00
    @baixiangcpp 是的,但是有时候我觉得抛出一个问题然后看大家讨论,也能学到很多,而且效率高一些
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5450 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 07:22 · PVG 15:22 · LAX 23:22 · JFK 02:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.