[ZZ]select 和 epoll

双LLM架构:提升AI代理系统安全性的关键技术 在人工智能领域,大语言模型(LLM)的安全防护是系统设计的核心挑战。传统单LLM架构存在单点失效风险,而双LLM架构通过决策隔离和权限分解机制,模拟人类组织的'双人复核'原则,显著提升系统安全性。该架构包含执行LLM和监督LLM两个组件,前者负责操作执行,后者专注安全审查,形成互补。关键技术实现涉及模型选型(如GPT-4与Claude-2组合)、安全通信管道(gRPC加密通道)和动态权限管理系统。在金融等行业实践中,这种架构已证明能有效防御SQL注入、权限提升等攻击,同时满足军工级安全要求。通过预验证缓存和 阅读详情
select 和 epoll

 

原文链接:http://www.cppblog.com/feixuwu/archive/2010/07/10/119995.html

 

最近有朋友在面试的时候被问了select 和epoll效率差的原因,和一般人一样,大部分都会回答select是轮询、epoll是触发式的,所以效率高。这个答案听上去很完美,大致也说出了二者的主要区别。
今天闲来无事,翻看了下内核代码,结合内核代码和大家分享下我的观点。

一、连接数

我本人也曾经在项目中用过select和epoll,对于select,感触最深的是linux下select最大数目限制(windows 下似乎没有限制),每个进程的select最多能处理FD_SETSIZE个FD(文件句柄),
如果要处理超过1024个句柄,只能采用多进程了。
常见的使用slect的多进程模型是这样的: 一个进程专门accept,成功后将fd通过unix socket传递给子进程处理,父进程可以根据子进程负载分派。曾经用过1个父进程+4个子进程 承载了超过4000个的负载。
这种模型在我们当时的业务运行的非常好。epoll在连接数方面没有限制,当然可能需要用户调用API重现设置进程的资源限制。

二、IO差别

1、select的实现

这段可以结合linux内核代码描述了,我使用的是2.6.28,其他2.6的代码应该差不多吧。
先看看select:
select系统调用的代码在fs/Select.c下,
asmlinkage long sys_select(int n, fd_set __user *inp, fd_set __user *outp,
fd_set __user *exp, struct timeval __user *tvp)
{
struct timespec end_time, *to = NULL;
struct timeval tv;
int ret;

if (tvp) {
if (copy_from_user(&tv, tvp, sizeof(tv)))
return -EFAULT;

to = &end_time;
if (poll_select_set_timeout(to,
tv.tv_sec + (tv.tv_usec / USEC_PER_SEC),
(tv.tv_usec % USEC_PER_SEC) * NSEC_PER_USEC))
return -EINVAL;
}

ret = core_sys_select(n, inp, outp, exp, to);
ret = poll_select_copy_remaining(&end_time, tvp, 1, ret);

return ret;
}
前面是从用户控件拷贝各个fd_set到内核空间,接下来的具体工作在core_sys_select中,
core_sys_select->do_select,真正的核心内容在do_select里:
int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
{
ktime_t expire, *to = NULL;
struct poll_wqueues table;
poll_table *wait;
int retval, i, timed_out = 0;
unsigned long slack = 0;

rcu_read_lock();
retval = max_select_fd(n, fds);
rcu_read_unlock();

if (retval < 0)
return retval;
n = retval;

poll_initwait(&table);
wait = &table.pt;
if (end_time && !end_time->tv_sec && !end_time->tv_nsec) {
wait = NULL;
timed_out = 1;
}

if (end_time && !timed_out)
slack = estimate_accuracy(end_time);

retval = 0;
for (;;) {
unsigned long *rinp, *routp, *rexp, *inp, *outp, *exp;

set_current_state(TASK_INTERRUPTIBLE);

inp = fds->in; outp = fds->out; exp = fds->ex;
rinp = fds->res_in; routp = fds->res_out; rexp = fds->res_ex;

for (i = 0; i < n; ++rinp, ++routp, ++rexp) {
unsigned long in, out, ex, all_bits, bit = 1, mask, j;
unsigned long res_in = 0, res_out = 0, res_ex = 0;
const struct file_operations *f_op = NULL;
struct file *file = NULL;

in = *inp++; out = *outp++; ex = *exp++;
all_bits = in | out | ex;
if (all_bits == 0) {
i += __NFDBITS;
continue;
}

for (j = 0; j < __NFDBITS; ++j, ++i, bit <<= 1) {
int fput_needed;
if (i >= n)
break;
if (!(bit & all_bits))
continue;
file = fget_light(i, &fput_needed);
if (file) {
f_op = file->f_op;
mask = DEFAULT_POLLMASK;
if (f_op && f_op->poll)
mask = (*f_op->poll)(file, retval ? NULL : wait);
fput_light(file, fput_needed);
if ((mask & POLLIN_SET) && (in & bit)) {
res_in |= bit;
retval++;
}
if ((mask & POLLOUT_SET) && (out & bit)) {
res_out |= bit;
retval++;
}
if ((mask & POLLEX_SET) && (ex & bit)) {
res_ex |= bit;
retval++;
}
}
}
if (res_in)
*rinp = res_in;
if (res_out)
*routp = res_out;
if (res_ex)
*rexp = res_ex;
cond_resched();
}
wait = NULL;
if (retval || timed_out || signal_pending(current))
break;
if (table.error) {
retval = table.error;
break;
}

/*
* If this is the first loop and we have a timeout
* given, then we convert to ktime_t and set the to
* pointer to the expiry value.
*/
if (end_time && !to) {
expire = timespec_to_ktime(*end_time);
to = &expire;
}

if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS))
timed_out = 1;
}
__set_current_state(TASK_RUNNING);

poll_freewait(&table);

return retval;
}
上面的代码很多,其实真正关键的代码是这一句:
mask = (*f_op->poll)(file, retval ? NULL : wait);
这个是调用文件系统的 poll函数,不同的文件系统poll函数自然不同,由于我们这里关注的是tcp连接,而socketfs的注册在 net/Socket.c里。
register_filesystem(&sock_fs_type);
socket文件系统的函数也是在net/Socket.c里:
static const struct file_operations socket_file_ops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.aio_read = sock_aio_read,
.aio_write = sock_aio_write,
.poll = sock_poll,
.unlocked_ioctl = sock_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_sock_ioctl,
#endif
.mmap = sock_mmap,
.open = sock_no_open, /* special open code to disallow open via /proc */
.release = sock_close,
.fasync = sock_fasync,
.sendpage = sock_sendpage,
.splice_write = generic_splice_sendpage,
.splice_read = sock_splice_read,
};
从sock_poll跟随下去,
最后可以到 net/ipv4/tcp.c的
unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait)
这个是最终的查询函数,
也就是说select 的核心功能是调用tcp文件系统的poll函数,不停的查询,如果没有想要的数据,主动执行一次调度(防止一直占用cpu),直到有一个连接有想要的消息为止。
从这里可以看出select的执行方式基本就是不同的调用poll,直到有需要的消息为止,如果select 处理的socket很多,这其实对整个机器的性能也是一个消耗。

2、epoll的实现

epoll的实现代码在 fs/EventPoll.c下,
由于epoll涉及到几个系统调用,这里不逐个分析了,仅仅分析几个关键点,
第一个关键点在
static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
struct file *tfile, int fd)
这是在我们调用sys_epoll_ctl 添加一个被管理socket的时候调用的函数,关键的几行如下:
epq.epi = epi;
init_poll_funcptr(&epq.pt, ep_ptable_queue_proc);

/*
* Attach the item to the poll hooks and get current event bits.
* We can safely use the file* here because its usage count has
* been increased by the caller of this function. Note that after
* this operation completes, the poll callback can start hitting
* the new item.
*/
revents = tfile->f_op->poll(tfile, &epq.pt);
这里也是调用文件系统的poll函数,不过这次初始化了一个结构,这个结构会带有一个poll函数的callback函数:ep_ptable_queue_proc,
在调用poll函数的时候,会执行这个callback,这个callback的功能就是将当前进程添加到 socket的等待进程上。
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
poll_table *pt)
{
struct epitem *epi = ep_item_from_epqueue(pt);
struct eppoll_entry *pwq;

if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
pwq->base = epi;
add_wait_queue(whead, &pwq->wait);
list_add_tail(&pwq->llink, &epi->pwqlist);
epi->nwait++;
} else {
/* We have to signal that an error occurred */
epi->nwait = -1;
}
}
注意到参数 whead 实际上是 sk->sleep,其实就是将当前进程添加到sk的等待队列里,当该socket收到数据或者其他事件触发时,会调用
sock_def_readable 或者sock_def_write_space 通知函数来唤醒等待进程,这2个函数都是在socket创建的时候填充在sk结构里的。
从前面的分析来看,epoll确实是比select聪明的多、轻松的多,不用再苦哈哈的去轮询了。

面试总结之select和epoll 前言是否用过 select、epoll,什么是IO多路复用,epoll 水平触发和边缘触发。解答IO多路复用IO多路复用是进程一种预先告知内核的能力,使得内核一旦发现进程指定的一个或多个IO条件就绪,它就通知进程。IO复用应用的场合:(1)当客户处理多个描述字时(一般是交互式输入和网络套接口),必须使用I/O复用。(2)当一个客户同时处理多个套接口时,而这种情况是可能的,但很少出现。(3)如果一个T 阅读详情

相关推荐

select,poll和epoll详解

select,poll和epoll详解 1.IO复用 为了解决大量客户端访问的问题,引入IO复用技术:一个进程可以同时对多个客户请求进行服务,复用一个进程对多个IO进行服务。IO读写的数据多数情况下未准备好,需要通过一个函数监听这些数据状态,一旦有数据可以读写就触发服务。elect,poll,epoll都是IO多路复用的机制,监视多个描述符,一旦某个描述符就绪,通知程序进行操作。 2.select 3.poll 4.epoll epoll 是Linux平台下的一种特有的多路复用IO实现方式,与传统的 sel

u010306832的博客 3479

select 和 epoll

<br />最近有朋友在面试的时候被问了select 和epoll效率差的原因,和一般人一样,大部分都会回答select是轮询、epoll是触发式的,所以效率高。这个答案听上去很完美,大致也说出了二者的主要区别。<br /> 今天闲来无事,翻看了下内核代码,结合内核代码和大家分享下我的观点。一、连接数<br /> 我本人也曾经在项目中用过select和epoll,对于select,感触最深的是linux下select最大数目限制(windows 下似乎没有限制),每个进程的select最多能处理FD_S

colder2008的专栏 748

epoll比select和poll高效的原因

我们通过比较select、poll和epoll处理I/O的过程来剖析其中的原因:1. 用户态将文件描述符传入内核的方式:select:创建3个文件描述符集并拷贝到内核中,分别监听读、写、异常动作。这里受到单个进程可以打开的fd数量限制,默认是1024。 poll:将传入的struct pollfd结构体数组拷贝到内核中进行监听。 epoll:执行epoll_create会在内核的高速

Move_now的博客 2567

大模型LLM全链路三层防御架构方案

本文提出了一套企业级大模型安全防护的三层纵深防御架构,覆盖从输入到输出的全链路安全风险。该体系包含11个标准化方案,分为三个层级: L1输入过滤层:在流量入口进行前置防护,包括文本转义清洗、多维度正则网关、轻量语义检测和RAG查询预处理,拦截已知攻击。 L2执行隔离层:架构层面的核心防护,采用分层Prompt隔离、硬编码+占位符传参、工具权限最小化、沙箱隔离和RAG文档后置清洗等措施。 L3输出校验层:对推理结果进行兜底防护,包括多维度安全审计和高危操作人工确认。 三大核心指导思想是:不可信输入全链路消毒、

d3y1`5 81_09 591

NRF24L01模块的5个常见问题及解决方案:从信号干扰到功耗优化

本文深入探讨NRF24L01无线模块在STM32开发中的5大常见问题及解决方案,包括通信距离优化、数据丢失排查、电源噪声抑制、SPI通信故障处理以及低功耗设计。通过代码示例和电路图分析,提供实用的优化策略,帮助开发者提升无线通信的稳定性和效率。

weixin_28256233的博客 226

JavaScript性能优化:全链路性能优化策略

JavaScript性能优化是提升Web应用质量的核心要素,直接影响用户体验与业务成果。研究表明,页面加载延迟1秒可能导致转化率下降7%。高效的JavaScript执行能减少主线程阻塞,避免动画卡顿或操作延迟,尤其在移动端低性能设备上更为关键。优化内存管理与减少冗余计算可降低浏览器资源消耗,防止因内存泄漏导致的崩溃,提升应用稳定性。在竞争激烈的互联网环境中,性能优势已成为产品差异化的关键因素,直接影响用户留存与商业价值。因此,性能优化应作为开发全周期的核心实践,而非事后补救措施。

weixin_49707375的博客 1270

Select、poll、Epoll、KQueue区别

在早期的文章《unix IO模型》中我们介绍了5种IO模型,如下图是几种IO模型的对比 几种IO模型的对比 从上面的图可以看出,从左到右,越往后,阻塞越少,理论上效率也就越优。 其中Select对应的是第三种IO模型:I/O Multiplexing IO多路复用模型,而epoll与kqueue其实和Select一样也属于I/O Multiplexing IO多路复用模型,只是相比于se...

GJQI12的专栏 2352

将Windbg附加到软件进程上排查异常闪退的问题

使用Windbg和Process Explorer排查因为内存泄漏导致的软件异常闪退问题。

dvlinker的技术专栏 1万+

python功能模块详述_深入理解python中的select模块

简介Python中的select模块专注于I/O多路复用,提供了select poll epoll三个方法(其中后两个在Linux中可用,windows仅支持select),另外也提供了kqueue方法(freeBSD系统)select方法进程指定内核监听哪些文件描述符(最多监听1024个fd)的哪些事件,当没有文件描述符事件发生时,进程被阻塞;当一个或者多个文件描述符事件发生时,进程被唤醒。...

weixin_39710179的博客 487

智能车图像处理24-进阶篇16--三叉路口的判断

这篇文章主要讲述图像处理中如何判断三叉路口并进行补线操作。

taiyuezyh的博客 1万+

车辆网络安全ISO/SAE 21434解读(一)概述

ISO/SAE 21434 《道路车辆 网络安全工程》是SAE和ISO共同制定的一项针对道路车辆的网络安全标准,它是一个面向汽车行业全供应链(OEM及各级供应商)的车辆网络安全管理指导文件

xiaoxiabang的博客 8426

SELECT和EPOLL的区别

适合连接数少且活跃度高的场景(主要还是因为实现简单,除此之外没了,在这个场景下,SELECT和EPOLL差别不大)“零拷贝”:数据从磁盘直接到页缓存,用户进程直接访问页缓存,避免了从内核缓冲区到用户缓冲区的拷贝。MMAP适合处理超大文件 - 1TB的文件,如果只访问其中1MB,就只会加载1MB到内存。传统IO方式:磁盘 → 内核缓冲区 → 用户缓冲区 (两次拷贝)mmap方式:磁盘 → 内存映射 → 直接访问 (零拷贝)使用位图(fd_set)表示文件描述符集合。支持水平触发(LT)和边缘触发(ET)

qq_33948769的博客 706

【CANoe示例分析】0002_SOMEIPDemo

该工程由Vector官方提供,作为仿真SOME/IP节点的示例。Demo中介绍了两种仿真SOME/IP节点的方法,一种是基于arxml数据库的仿真,另一种是没有数据库(arxml、fibex)的仿真。无论是哪种形式的仿真,如果想要通过CAPL程序接收或者发送SOME/IP信息,都需要添加交互层的信息,这些信息可以通过添加DLL文件实现,DLL文件路径在CANoe安装目录下的Exec32文件中。

jasonj333 3518

epoll、poll、select的原理和区别

一、什么是epoll? epoll是一种I/O事件通知机制,是linux 内核实现IO多路复用的一个实现。IO多路复用是指,在一个操作里同时监听多个输入输出源,在其中一个或多个输入输出源可用的时候返回,然后对其的进行读写操作。 epoll有两种工作方式,ET-水平触发 和 LT-边缘触发(默认工作方式),主要区别是: LT,内核通知你fd是否就绪,如果没有处理,则会持续通知。而ET,内核只通知一次。 二、epoll的三个函数 int epoll_create(int size) size参数告诉内核这

wwwvipp的博客 5万+

Python 爬虫实战:拼多多商品评论情感分析(含词云生成与差评预警)

在电商行业竞争日益激烈的当下,商家对商品评论的分析需求愈发迫切。通过 Python 爬虫收集拼多多商品评论,并结合情感分析、词云可视化及差评预警技术,商家可精准洞察消费者反馈,优化商品与服务。本文将深度剖析从爬虫搭建到数据挖掘的关键环节,助力读者构建全流程电商评论分析系统。

yansideyucsdn的博客 1450

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

select和epoll的区别,以及epoll的优势所在

select的缺点: 支持的fd数量有限: 单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量,但由于select采用轮询的方式扫描文件描述符,文件描述符数量越多,性能越差;(在linux内核头文件中,有这样的定义:#define单个进程能够监视的文件描述符的数量存在最大限制,通常是1024,当然可以更改数量,但由于select采用轮询的方式扫描文件描述符,文件描...

gymaisyl的博客 2万+

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

select和epoll的详细区别

selectepollselect和epoll都是 Linux 中用于 I/O 多路复用的机制,但epoll更加高效且适用于大规模并发场景。select的性能会随着监视的文件描述符数量线性下降,而epoll使用事件通知机制,性能几乎不受文件描述符数量的影响。在大多数高并发场景下,epoll是首选;而对于小规模应用或跨平台需求时,可以考虑使用select。通过理解select和epoll的不同特性,可以在不同场景中选择最合适的 I/O 复用技术来实现高效的 I/O 处理。

h52013141的博客 2893

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

关于select、poll和epoll

探究IO多路复用

2301_76846772的博客 1281

select、poll和epoll

举个例子,假设客户端一次性发来了4K数据 ,但是服务器recv函数定义的buffer大小仅为1024字节,那么一次肯定是不能将所有数据都读取完的,这时候就会继续触发可读事件,直到所有数据都处理完成。里面的fd,它代表一个文件描述符,初始化的时候传入需要监听的文件描述符,当监听返回时,此处会传出一个有事件发生的文件描述符,因此,无需我们遍历所有的文件描述符,就可以得到结果了。epoll的优点显而易见,它解决了poll需要遍历所有注册的fd的问题,只需要关心触发了事件的极少量fd即可,大大提升了效率。

achouyihao的博客 863

【Linux】select、poll和epoll详解

正如上文介绍 select 函数相关宏所介绍的,select 函数调用前后可能会修改 readfds、writefds 和 exceptfds 这三个集合中的内容,所以如果读者想下次调用 select 函数时复用这些 fd_set 变量,记得在下次调用前使用 FD_ZERO 将 fd_set 清零,然后再调用 FD_SET 将需要检测事件的 fd 重新添加到 fd_set。在 Linux 平台上,select 函数的实现是利用 poll 函数的,有兴趣的读者可以查找一下相关的资料来阅读一下。

m0_73839343的博客 1262

Select、Poll和Epoll

看到一篇写得很不错的博文,有必要收藏一下: 原文:https://cloud.tencent.com/developer/article/1005481 提到select、poll、epoll相信大家都耳熟能详了,三个都是IO多路复用的机制,可以监视多个描述符的读/写等事件,一旦某个描述符就绪(一般是读或者写事件发生了),就能够将发生的事件通知给关心的应用程序去处理该事件。本质上,select...

ajuse的博客 4269

select、poll和epoll的区别

本文总结了从阻塞I/O模型到多路复用I/O模型的演变,以及select、poll、epoll三者各自优缺点。

weixin_38597669的博客 2203

epoll和select

先说下本文框架,先是问题引出,然后概括两个机制的区别和联系,最后介绍每个接口的用法 一、问题引出 联系区别 问题的引出,当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或者多线程,但是这种方法会造成程序的复杂,而且对与进程与线程的创建维护也需要很多的...

小胖的博客 237

epoll和select的区别

要了解epoll和select的区别,首先来理解一下epoll和select各自的功能和属性。poll和epoll和select都是多路复用下的一种机制,多路复用I/O就是通过一种机制,可以监视多个文件描述符,一旦某个文件描述符就绪,就通知程序该文件描述符可以进行读写操作。select():用于确定一个或多个套接口的状态。 select的几大缺点(不可忽视): 1、每次调用sel

qq_34022469的博客 1万+
上一篇: [ZZ]POSIX thread (pthread) 简介
下一篇: [ZZ]valgrind 手册
leonsc
博客等级 码龄18年 29粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值