1
soulzz 2019-09-11 20:21:22 +08:00
建议了解下 nio
|
2
xeaglex 2019-09-11 20:43:37 +08:00 3
监听无非就两大类:主动轮询,或者被动通知。
轮询就是像你说的,疯狂检查。通知就比如现在常说的异步机制。 |
3
zxle 2019-09-11 20:45:39 +08:00 1
lz 说的这种方式一般属于操作系统层面干的活儿
|
4
seeker 2019-09-11 20:46:47 +08:00
监听是啥含义最好看看是啥场景,可能不好概括。
如果你说的是 linux c 语言 socket 编程,那么是先 bind ip 端口,然后死循环 accept,没有间隔时间,因为 accept 函数是阻塞的。 高级语言 /框架可能用 listen 而不是用 bind 最为函数 /方法名,做的事情很可能有区别。不过底层的话,应该差不多。 |
5
Fishdrowned 2019-09-11 21:08:30 +08:00 1
没错,最终需要有人在那里死循环
|
6
wwbfred 2019-09-11 21:18:23 +08:00
个人理解的监听就是轮询.
无论上层表现成什么方便高效的方式,底层都是轮询. 只是不同的轮询方式效率不同. 如果有误还请指正~ |
7
Buges 2019-09-11 21:21:46 +08:00 via Android
应该不能说是死循环,而是“等待”(也就是阻塞)
|
8
Fishdrowned 2019-09-11 21:22:57 +08:00 2
监听端口的话估计是这样:
网卡收到报文 -> 发起硬件中断 -> CPU 停下来处理这个中断 -> OS 中断处理 -> 应用程序 这样看起来不清楚 OS 是否需要死循环,或许不需要 |
9
Fishdrowned 2019-09-11 21:23:48 +08:00
不过 CPU 就是在无时无刻地死循环,这个是跑不了的
|
10
billlee 2019-09-11 21:34:11 +08:00
@Fishdrowned #9 CPU 明明可以 halt 的
|
11
lilydjwg 2019-09-11 21:38:39 +08:00 1
@Fishdrowned #9 不对。网络处理有两种方式:轮询和中断。通用计算机中,通常操作系统会通过中断的方式来获知有新数据到达。
CPU 没事干了怎么办?降频省电啊!一直没事干怎么办?电力紧张的话(比如移动设备),可以休眠啊。 至于用户态的监听( listen )。呃,它就是设置一下连接的状态而已……用户态程序要获知新数据的到达,需要使用阻塞调用( accept )、I/O 复用接口( epoll / poll / select )、异步 I/O 等方案。 |
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 标志。 |
14
starsriver 2019-09-12 06:50:47 +08:00 via Android
如果你了解硬件设备,你就会知道看门狗而不会来问这么蠢的问题。
虽然现代计算机端口属于软件领域,但是和硬件差不多也有看门狗,不可能死循环轮寻,win10 的程序无响应了解一下?其实主要是基于任务调度,os 的触发器,就是别人说的中断。每个任务,进程,线程都有自己的编号 pid,而 cpu 每时每刻都会产生随即数来决定该为哪个服务分配资源,就行隔离,这部分基于硬件。端口也可以看作一个固定的分配号,当对应编号及缓存地址存在数据缓存或者出现头数据,触发器会开始工作,向 cpu 请求处理,处理完后数据被寄存到内存里,当前任务完成并通知其他任务继续进行 |
15
mikulch 2019-09-12 06:53:53 +08:00 via iPhone
挺感兴趣这个话题的,希望有人能够通俗易懂的讲清楚。
|
16
jedihy 2019-09-12 07:06:38 +08:00
OS 不会死循环的。
Windows: 网络 IO 都是 INT->ISR->Queue DPC ==> NDIS DPC -> LWF chain -> TCPIP (-> AFD -> Winsock1) |
17
xuxuzhaozhao 2019-09-12 07:22:01 +08:00 via iPhone
@starsriver 你打娘胎生下来就会???这个弱智那个弱智,你才最弱智。
|
18
smallpython OP @Fishdrowned 明白了,程序里设置的一旦触发了什么事件就去做什么事的这种逻辑.是利用了 cpu 是在无限死循环的特征.因为如果 cpu 不循环的话,那么它就停止了.
既然 cpu 是在死循环, 那么操作系统就可以利用这个循环来实现如上所述的"触发"这个动词的效果,就可以实现通知的功能. 就好像我并没有主动监听小明的声音,但是只要小明说话了,我就可以接受到小明的声音,这是因为我的大脑本身是在监听外部的所有信息,所以我的耳朵就不需要主动去监听小明的声音,就可以实现小明的声音触发我的动作这种效果. 可以这样理解吗? |
19
smallpython OP @lilydjwg 可是当中断的时候, 程序又是怎么知道它什么时候该继续呢?
我的理解还是因为它轮询的判断了某一个条件, 然后才能知道是不是该继续了. 表述可能有点拟人化,但是我觉得这个道理应该是成立的. 就好像单核的多进程是 CPU 快速切换的假象,而不是真的有多个进程 我想知道所谓的中断,在最底层的实现,是不是也得有一个死循环的判断逻辑 |
20
jworg 2019-09-12 10:01:47 +08:00
@smallpython 这里的部分回答应该能解释部分吧 https://www.zhihu.com/question/21440586
|
21
guolaopi 2019-09-12 10:22:29 +08:00
@smallpython #18
em.....也不知道我是不是理解有偏差。但是我觉得不能是单纯简单的“CPU 死循环”,可以写个程序把所有端口都监听起来看一下 CPU 的变化。。。 |
22
smallpython OP @jworg 还是知乎大神多啊
|
23
lilydjwg 2019-09-12 11:29:41 +08:00
@smallpython #19 「中断」是一个术语。CPU 工作的时候,网卡过来有事打断了 CPU,这就叫作中断。CPU 这时候根据中断向量表,找到对应于网卡中断的处理程序,然后 CPU 就知道有网络数据过来了。
只有在很繁忙的设备上才会使用轮询去处理网络数据。 当然,网卡是一直处于准备好接收数据的状态的。 |
24
lilydjwg 2019-09-12 11:35:04 +08:00 2
@starsriver #14 你觉得你自己不蠢,可你说的也没几个对的。
不可能死循环轮寻 => 处理大流量的设备上是可能的,因为几乎每次轮询都有数据,效率比中断高不少 os 的触发器,就是别人说的中断 => 这里讨论的是硬件中断 每时每刻都会产生随即数来决定该为哪个服务分配资源 => 产生随机数挺累的,CPU 怎么可能一直去做,还干不干活了?任务调度是有算法的,一般使用带优先级的队列或者位图之类的东西,并不会使用缓慢的随机数 当对应编号及缓存地址存在数据缓存或者出现头数据,触发器会开始工作 => 并没有一个叫「触发器」的硬件会帮忙 CPU 做这部分处理 处理完后数据被寄存到内存里 => CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了 |
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 层面的说的是软中断,总数差不多是硬件中断的五分之一。 |
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 可不放心用户态的程序乱搞中断。 软件中断我没怎么了解过,刚看了一下维基百科。原来访存违例和调试啥的都是软件中断实现的。所以,软件中断也不是用户态进程能够直接接触到的。 我对硬件部分不太了解,因为我是软件工程师嘛。 |
28
pussy2019 2019-09-12 17:54:21 +08:00
@starsriver 虽然我不太懂,但丝毫不影响我喷你,你就是个蠢货,知道点皮毛就不知道怎么得瑟了,你要上天啊
|
29
starsriver 2019-09-12 18:00:27 +08:00 via Android 2
@pussy2019 虫子总是到处飞?
|
30
zlyang 2019-09-12 18:27:43 +08:00
说是 “监听” 不如说是 “记录”,底层接收(轮询亦或中断)网卡芯片传送过来的数据投递到网络子系统,网络子系统内部会检索有无 “目的端口” 这一记录项,然后再通过记录项对应的参数传递到对应的应用中,当然此时应用可能在轮询也可能处于阻塞中。
|
31
dinjufen 2019-09-12 18:35:06 +08:00
希望有大佬来详细解读一下
|
32
zivyou 2019-09-12 18:36:37 +08:00
硬件中断,epoll 了解一下
|
33
annielong 2019-09-12 18:44:30 +08:00
问的是程序中的监听,不是系统的
|
34
ylrshui 2019-09-12 19:37:17 +08:00 via iPhone
监听端口,端口分为硬件端口和软件上的端口
硬件端口一直在接收数据(电平一直在变化),能不能被处理就看你的程序是不是在正确的时刻运行处理程序,在没有缓存的硬件结构里,数据到达时没有处理,那就丢了 网卡(一般)并不会区分收到的数据来自哪个应用程序和应该给哪个程序,它收到数据(包括预先定义好的所谓的端口号在硬件来看也只是数据),交给驱动软件处理,提取数据里的端口号(软件端口),再交给其对应的上层软件处理 至于上层软件能不能及时正确处理,可以轮询,也可以在硬件上设个触发器,让处理器在时间到或有对应事件发生时,让它及时处理,至于触发器,有多个,有优先级,由程序设定,触发时也能告诉处理器从哪段代码开始执行 |
35
no1xsyzy 2019-09-12 19:47:56 +08:00
|
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 试试? |
37
no1xsyzy 2019-09-12 20:18:20 +08:00
|
38
reus 2019-09-12 20:21:43 +08:00
思而不学
|
39
lilydjwg 2019-09-12 20:22:02 +08:00
|
40
lilydjwg 2019-09-12 20:24:45 +08:00
@no1xsyzy #36 这是 /dev/urandom 和 yes 的差别:
https://img.vim-cn.com/85/e96192a830c7b248c5bf60bbbf84c18156bc8d.png |
41
no1xsyzy 2019-09-12 20:41:29 +08:00
@lilydjwg #24
> CPU 是先复制网络数据到内存里,再决定要如何处理。因为网卡的存储空间有限,你不及时处理就丢包了 你看没看新闻…… Intel 因为让网卡能够直接访问缓存导致了漏洞 所以不一定进内存 |
42
baixiangcpp 2019-09-12 20:53:37 +08:00
这个算不算读书读的不多,想的太多(无恶意
|
43
okwork 2019-09-12 21:00:00 +08:00 via Android
网卡接收的信号,和敲击键盘的信号本质都是一样电信号变化,监听的优先级看系统逻辑。比如可以通过网络远程开机、也可以通过键盘密码开机,感觉应该是一个等级的监听。
|
44
no1xsyzy 2019-09-12 21:38:20 +08:00
@lilydjwg 其实我就是想提醒你加 pv
慢点,难道不是 “gdb 是直接调用 ptrace 的,所以是直接使用接触软中断” 吗? ptrace 不就是软中断入口吗?不然直接插 x86 的被调指令?那是硬中断…… |
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 这样设计的。 |
46
b00tyhunt3r 2019-09-13 14:04:53 +08:00 via iPhone
@smallpython csapp 第八章
|
47
smallpython OP @baixiangcpp 是的,但是有时候我觉得抛出一个问题然后看大家讨论,也能学到很多,而且效率高一些
|