首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  程序员

程序中监听的含义?

  •  
  •   smallpython · 4 天前 · 3415 次点击
    是不是就是说死循环去访问一个资源?

    比如监听端口

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

    如果是的话,那么每次检查的间隔时间一般都设置为多久呢?
    46 回复  |  直到 2019-09-13 14:04:53 +08:00
        1
    soulzz   4 天前
    建议了解下 nio
        2
    xeaglex   4 天前   ♥ 3
    监听无非就两大类:主动轮询,或者被动通知。

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

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

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

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

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

    accept 是阻塞的这说法也不对。accept 是否阻塞,取决于套接字是否设置了 O_NONBLOCK 标志。
        13
    seeker   4 天前
    @lilydjwg 谢谢指正。
        14
    starsriver   4 天前 via Android
    如果你了解硬件设备,你就会知道看门狗而不会来问这么蠢的问题。

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

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

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

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

    当然,网卡是一直处于准备好接收数据的状态的。
        24
    lilydjwg   3 天前   ♥ 2
    @starsriver #14 你觉得你自己不蠢,可你说的也没几个对的。

    不可能死循环轮寻 => 处理大流量的设备上是可能的,因为几乎每次轮询都有数据,效率比中断高不少
    os 的触发器,就是别人说的中断 => 这里讨论的是硬件中断
    每时每刻都会产生随即数来决定该为哪个服务分配资源 => 产生随机数挺累的,CPU 怎么可能一直去做,还干不干活了?任务调度是有算法的,一般使用带优先级的队列或者位图之类的东西,并不会使用缓慢的随机数
    当对应编号及缓存地址存在数据缓存或者出现头数据,触发器会开始工作 => 并没有一个叫「触发器」的硬件会帮忙 CPU 做这部分处理
    处理完后数据被寄存到内存里 => CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了
        25
    lilydjwg   3 天前
    @guolaopi #21 这个……内存的变化应该更明显。
        26
    starsriver   3 天前 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 层面的说的是软中断,总数差不多是硬件中断的五分之一。
        27
    lilydjwg   3 天前
    @starsriver #26

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    至于上层软件能不能及时正确处理,可以轮询,也可以在硬件上设个触发器,让处理器在时间到或有对应事件发生时,让它及时处理,至于触发器,有多个,有优先级,由程序设定,触发时也能告诉处理器从哪段代码开始执行
        35
    no1xsyzy   3 天前
        36
    no1xsyzy   3 天前
    @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 试试?
        37
    no1xsyzy   3 天前
    @lilydjwg
    > 原来访存违例和调试啥的都是软件中断实现的
    > 软件中断也不是用户态进程能够直接接触到的
    调试器( gdb )不是用户态程序?
        38
    reus   3 天前
    思而不学
        39
    lilydjwg   3 天前
    @no1xsyzy #36 哦,我忘记说中间插入个 pv 看数据量了。你可以对比一下 /dev/urandom 和 yes 的生成速率。
    @no1xsyzy #37 但是 gdb 是调用内核提供的 API ( ptrace )的呀,是间接的呢。
        40
    lilydjwg   3 天前
        41
    no1xsyzy   3 天前
    @lilydjwg #24
    > CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了
    你看没看新闻…… Intel 因为让网卡能够直接访问缓存导致了漏洞
    所以不一定进内存
        42
    baixiangcpp   3 天前
    这个算不算读书读的不多,想的太多(无恶意
        43
    okwork   3 天前 via Android
    网卡接收的信号,和敲击键盘的信号本质都是一样电信号变化,监听的优先级看系统逻辑。比如可以通过网络远程开机、也可以通过键盘密码开机,感觉应该是一个等级的监听。
        44
    no1xsyzy   3 天前
    @lilydjwg 其实我就是想提醒你加 pv

    慢点,难道不是 “gdb 是直接调用 ptrace 的,所以是直接使用接触软中断” 吗?
    ptrace 不就是软中断入口吗?不然直接插 x86 的被调指令?那是硬中断……
        45
    jedihy   3 天前
    其实这个问题本质上是在问 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 这样设计的。
        46
    b00tyhunt3r   2 天前 via iPhone
    @smallpython csapp 第八章
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   4039 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 26ms · UTC 02:38 · PVG 10:38 · LAX 19:38 · JFK 22:38
    ♥ Do have faith in what you're doing.