1 use core::{ 2 any::Any, 3 fmt::Debug, 4 sync::atomic::{AtomicBool, Ordering}, 5 }; 6 7 use alloc::{ 8 collections::LinkedList, 9 sync::{Arc, Weak}, 10 vec::Vec, 11 }; 12 use intertrait::CastFromSync; 13 use system_error::SystemError; 14 15 use crate::{ 16 filesystem::vfs::{ 17 file::{File, FileMode}, 18 FilePrivateData, IndexNode, Metadata, 19 }, 20 include::bindings::bindings::INT32_MAX, 21 libs::{ 22 rbtree::RBTree, 23 rwlock::RwLock, 24 spinlock::{SpinLock, SpinLockGuard}, 25 wait_queue::WaitQueue, 26 }, 27 process::ProcessManager, 28 sched::{schedule, SchedMode}, 29 time::{ 30 timer::{next_n_us_timer_jiffies, Timer, WakeUpHelper}, 31 PosixTimeSpec, 32 }, 33 }; 34 35 pub mod syscall; 36 37 #[derive(Debug, Clone)] 38 pub struct LockedEventPoll(Arc<SpinLock<EventPoll>>); 39 40 /// 内核的Epoll对象结构体,当用户创建一个Epoll时,内核就会创建一个该类型对象 41 /// 它对应一个epfd 42 #[derive(Debug)] 43 pub struct EventPoll { 44 /// epoll_wait用到的等待队列 45 epoll_wq: WaitQueue, 46 /// 维护所有添加进来的socket的红黑树 47 ep_items: RBTree<i32, Arc<EPollItem>>, 48 /// 接收就绪的描述符列表 49 ready_list: LinkedList<Arc<EPollItem>>, 50 /// 是否已经关闭 51 shutdown: AtomicBool, 52 self_ref: Option<Weak<SpinLock<EventPoll>>>, 53 } 54 55 impl EventPoll { 56 pub const EP_MAX_EVENTS: u32 = INT32_MAX / (core::mem::size_of::<EPollEvent>() as u32); 57 /// 用于获取inode中的epitem队列 58 pub const ADD_EPOLLITEM: u32 = 0x7965; 59 pub fn new() -> Self { 60 Self { 61 epoll_wq: WaitQueue::default(), 62 ep_items: RBTree::new(), 63 ready_list: LinkedList::new(), 64 shutdown: AtomicBool::new(false), 65 self_ref: None, 66 } 67 } 68 } 69 70 impl Default for EventPoll { 71 fn default() -> Self { 72 Self::new() 73 } 74 } 75 76 /// EpollItem表示的是Epoll所真正管理的对象 77 /// 每当用户向Epoll添加描述符时都会注册一个新的EpollItem,EpollItem携带了一些被监听的描述符的必要信息 78 #[derive(Debug)] 79 pub struct EPollItem { 80 /// 对应的Epoll 81 epoll: Weak<SpinLock<EventPoll>>, 82 /// 用户注册的事件 83 event: RwLock<EPollEvent>, 84 /// 监听的描述符 85 fd: i32, 86 /// 对应的文件 87 file: Weak<File>, 88 } 89 90 impl EPollItem { 91 pub fn new( 92 epoll: Weak<SpinLock<EventPoll>>, 93 events: EPollEvent, 94 fd: i32, 95 file: Weak<File>, 96 ) -> Self { 97 Self { 98 epoll, 99 event: RwLock::new(events), 100 fd, 101 file, 102 } 103 } 104 105 pub fn epoll(&self) -> Weak<SpinLock<EventPoll>> { 106 self.epoll.clone() 107 } 108 109 pub fn event(&self) -> &RwLock<EPollEvent> { 110 &self.event 111 } 112 113 pub fn file(&self) -> Weak<File> { 114 self.file.clone() 115 } 116 117 pub fn fd(&self) -> i32 { 118 self.fd 119 } 120 121 /// ## 通过epoll_item来执行绑定文件的poll方法,并获取到感兴趣的事件 122 fn ep_item_poll(&self) -> EPollEventType { 123 let file = self.file.upgrade(); 124 if file.is_none() { 125 return EPollEventType::empty(); 126 } 127 if let Ok(events) = file.unwrap().poll() { 128 let events = events as u32 & self.event.read().events; 129 return EPollEventType::from_bits_truncate(events); 130 } 131 return EPollEventType::empty(); 132 } 133 } 134 135 pub trait KernelIoctlData: Send + Sync + Any + Debug + CastFromSync {} 136 137 impl KernelIoctlData for EPollItem {} 138 139 /// ### Epoll文件的私有信息 140 #[derive(Debug, Clone)] 141 pub struct EPollPrivateData { 142 epoll: LockedEventPoll, 143 } 144 145 /// ### 该结构体将Epoll加入文件系统 146 #[derive(Debug)] 147 pub struct EPollInode { 148 epoll: LockedEventPoll, 149 } 150 151 impl EPollInode { 152 pub fn new(epoll: LockedEventPoll) -> Arc<Self> { 153 Arc::new(Self { epoll }) 154 } 155 } 156 157 impl IndexNode for EPollInode { 158 fn read_at( 159 &self, 160 _offset: usize, 161 _len: usize, 162 _buf: &mut [u8], 163 _data: SpinLockGuard<FilePrivateData>, 164 ) -> Result<usize, SystemError> { 165 Err(SystemError::ENOSYS) 166 } 167 168 fn write_at( 169 &self, 170 _offset: usize, 171 _len: usize, 172 _buf: &[u8], 173 _data: SpinLockGuard<FilePrivateData>, 174 ) -> Result<usize, SystemError> { 175 Err(SystemError::ENOSYS) 176 } 177 178 fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> { 179 // 需要实现epoll嵌套epoll时,需要实现这里 180 todo!() 181 } 182 183 fn fs(&self) -> Arc<dyn crate::filesystem::vfs::FileSystem> { 184 todo!() 185 } 186 187 fn as_any_ref(&self) -> &dyn core::any::Any { 188 self 189 } 190 191 fn list(&self) -> Result<Vec<alloc::string::String>, SystemError> { 192 Err(SystemError::ENOSYS) 193 } 194 195 fn metadata(&self) -> Result<Metadata, SystemError> { 196 Ok(Metadata::default()) 197 } 198 199 fn close(&self, _data: SpinLockGuard<FilePrivateData>) -> Result<(), SystemError> { 200 // 释放资源 201 let mut epoll = self.epoll.0.lock_irqsave(); 202 203 // 唤醒epoll上面等待的所有进程 204 epoll.shutdown.store(true, Ordering::SeqCst); 205 epoll.ep_wake_all(); 206 207 let fds = epoll.ep_items.keys().cloned().collect::<Vec<_>>(); 208 209 // 清理红黑树里面的epitems 210 for fd in fds { 211 let file = ProcessManager::current_pcb() 212 .fd_table() 213 .read() 214 .get_file_by_fd(fd); 215 216 if file.is_some() { 217 file.unwrap().remove_epoll(&Arc::downgrade(&self.epoll.0))?; 218 } 219 220 epoll.ep_items.remove(&fd); 221 } 222 223 Ok(()) 224 } 225 226 fn open( 227 &self, 228 _data: SpinLockGuard<FilePrivateData>, 229 _mode: &FileMode, 230 ) -> Result<(), SystemError> { 231 Ok(()) 232 } 233 } 234 235 impl EventPoll { 236 /// ## 创建epoll对象 237 /// 238 /// ### 参数 239 /// - flags: 创建的epoll文件的FileMode 240 /// 241 /// ### 返回值 242 /// - 成功则返回Ok(fd),否则返回Err 243 pub fn do_create_epoll(flags: FileMode) -> Result<usize, SystemError> { 244 if !flags.difference(FileMode::O_CLOEXEC).is_empty() { 245 return Err(SystemError::EINVAL); 246 } 247 248 // 创建epoll 249 let epoll = LockedEventPoll(Arc::new(SpinLock::new(EventPoll::new()))); 250 epoll.0.lock_irqsave().self_ref = Some(Arc::downgrade(&epoll.0)); 251 252 // 创建epoll的inode对象 253 let epoll_inode = EPollInode::new(epoll.clone()); 254 255 let mut ep_file = File::new( 256 epoll_inode, 257 FileMode::O_RDWR | (flags & FileMode::O_CLOEXEC), 258 )?; 259 260 // 设置ep_file的FilePrivateData 261 ep_file.private_data = SpinLock::new(FilePrivateData::EPoll(EPollPrivateData { epoll })); 262 263 let current_pcb = ProcessManager::current_pcb(); 264 let fd_table = current_pcb.fd_table(); 265 let mut fd_table_guard = fd_table.write(); 266 267 let fd = fd_table_guard.alloc_fd(ep_file, None)?; 268 269 Ok(fd as usize) 270 } 271 272 /// ## epoll_ctl的具体实现 273 /// 274 /// 根据不同的op对epoll文件进行增删改 275 /// 276 /// ### 参数 277 /// - epfd: 操作的epoll文件描述符 278 /// - op: 对应的操作 279 /// - fd: 操作对应的文件描述符 280 /// - epds: 从用户态传入的event,若op为EpollCtlAdd,则对应注册的监听事件,若op为EPollCtlMod,则对应更新的事件,删除操作不涉及此字段 281 /// - nonblock: 定义这次操作是否为非阻塞(有可能其他地方占有EPoll的锁) 282 pub fn do_epoll_ctl( 283 epfd: i32, 284 op: EPollCtlOption, 285 fd: i32, 286 epds: &mut EPollEvent, 287 nonblock: bool, 288 ) -> Result<usize, SystemError> { 289 let current_pcb = ProcessManager::current_pcb(); 290 let fd_table = current_pcb.fd_table(); 291 let fd_table_guard = fd_table.read(); 292 293 // 获取epoll和对应fd指向的文件 294 let ep_file = fd_table_guard 295 .get_file_by_fd(epfd) 296 .ok_or(SystemError::EBADF)?; 297 let dst_file = fd_table_guard 298 .get_file_by_fd(fd) 299 .ok_or(SystemError::EBADF)?; 300 301 // 检查是否允许 EPOLLWAKEUP 302 if op != EPollCtlOption::Del { 303 epds.events &= !EPollEventType::EPOLLWAKEUP.bits(); 304 } 305 306 let events = EPollEventType::from_bits_truncate(epds.events); 307 308 // 检查获取到的两个文件的正确性 309 // 首先是不能自己嵌套自己 310 // 然后ep_file必须是epoll文件 311 if Arc::ptr_eq(&ep_file, &dst_file) || !Self::is_epoll_file(&ep_file) { 312 return Err(SystemError::EINVAL); 313 } 314 315 if op != EPollCtlOption::Del && events.contains(EPollEventType::EPOLLEXCLUSIVE) { 316 // epoll独占模式下不允许EpollCtlMod 317 if op == EPollCtlOption::Mod { 318 return Err(SystemError::EINVAL); 319 } 320 321 // 不支持嵌套的独占唤醒 322 if op == EPollCtlOption::Add && Self::is_epoll_file(&dst_file) 323 || !events 324 .difference(EPollEventType::EPOLLEXCLUSIVE_OK_BITS) 325 .is_empty() 326 { 327 return Err(SystemError::EINVAL); 328 } 329 } 330 331 // 从FilePrivateData获取到epoll 332 if let FilePrivateData::EPoll(epoll_data) = &*ep_file.private_data.lock() { 333 let mut epoll_guard = { 334 if nonblock { 335 // 如果设置非阻塞,则尝试获取一次锁 336 if let Ok(guard) = epoll_data.epoll.0.try_lock_irqsave() { 337 guard 338 } else { 339 return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); 340 } 341 } else { 342 epoll_data.epoll.0.lock_irqsave() 343 } 344 }; 345 346 if op == EPollCtlOption::Add { 347 // TODO: 循环检查是否为epoll嵌套epoll的情况,如果是则需要检测其深度 348 // 这里是需要一种检测算法的,但是目前未考虑epoll嵌套epoll的情况,所以暂时未实现 349 // Linux算法:https://code.dragonos.org.cn/xref/linux-6.1.9/fs/eventpoll.c?r=&mo=56953&fi=2057#2133 350 if Self::is_epoll_file(&dst_file) { 351 todo!(); 352 } 353 } 354 355 let ep_item = epoll_guard.ep_items.get(&fd); 356 match op { 357 EPollCtlOption::Add => { 358 // 如果已经存在,则返回错误 359 if ep_item.is_some() { 360 return Err(SystemError::EEXIST); 361 } 362 // 设置epoll 363 let epitem = Arc::new(EPollItem::new( 364 Arc::downgrade(&epoll_data.epoll.0), 365 *epds, 366 fd, 367 Arc::downgrade(&dst_file), 368 )); 369 Self::ep_insert(&mut epoll_guard, dst_file, epitem)?; 370 } 371 EPollCtlOption::Del => { 372 // 不存在则返回错误 373 if ep_item.is_none() { 374 return Err(SystemError::ENOENT); 375 } 376 // 删除 377 Self::ep_remove(&mut epoll_guard, fd, Some(dst_file))?; 378 } 379 EPollCtlOption::Mod => { 380 // 不存在则返回错误 381 if ep_item.is_none() { 382 return Err(SystemError::ENOENT); 383 } 384 let ep_item = ep_item.unwrap().clone(); 385 if ep_item.event.read().events & EPollEventType::EPOLLEXCLUSIVE.bits() != 0 { 386 epds.events |= 387 EPollEventType::EPOLLERR.bits() | EPollEventType::EPOLLHUP.bits(); 388 389 Self::ep_modify(&mut epoll_guard, ep_item, epds)?; 390 } 391 } 392 } 393 } 394 395 Ok(0) 396 } 397 398 /// ## epoll_wait的具体实现 399 pub fn do_epoll_wait( 400 epfd: i32, 401 epoll_event: &mut [EPollEvent], 402 max_events: i32, 403 timespec: Option<PosixTimeSpec>, 404 ) -> Result<usize, SystemError> { 405 let current_pcb = ProcessManager::current_pcb(); 406 let fd_table = current_pcb.fd_table(); 407 let fd_table_guard = fd_table.read(); 408 409 // 获取epoll文件 410 let ep_file = fd_table_guard 411 .get_file_by_fd(epfd) 412 .ok_or(SystemError::EBADF)?; 413 414 drop(fd_table_guard); 415 416 // 确保是epoll file 417 if !Self::is_epoll_file(&ep_file) { 418 return Err(SystemError::EINVAL); 419 } 420 421 // 从epoll文件获取到epoll 422 let mut epolldata = None; 423 if let FilePrivateData::EPoll(epoll_data) = &*ep_file.private_data.lock() { 424 epolldata = Some(epoll_data.clone()) 425 } 426 if let Some(epoll_data) = epolldata { 427 let epoll = epoll_data.epoll.clone(); 428 let epoll_guard = epoll.0.lock_irqsave(); 429 430 let mut timeout = false; 431 if let Some(timespec) = timespec { 432 if !(timespec.tv_sec > 0 || timespec.tv_nsec > 0) { 433 // 非阻塞情况 434 timeout = true; 435 } 436 } 437 // 判断epoll上有没有就绪事件 438 let mut available = epoll_guard.ep_events_available(); 439 440 drop(epoll_guard); 441 loop { 442 if available { 443 // 如果有就绪的事件,则直接返回就绪事件 444 return Self::ep_send_events(epoll.clone(), epoll_event, max_events); 445 } 446 447 if epoll.0.lock_irqsave().shutdown.load(Ordering::SeqCst) { 448 // 如果已经关闭 449 return Err(SystemError::EBADF); 450 } 451 452 // 如果超时 453 if timeout { 454 return Ok(0); 455 } 456 457 // 自旋等待一段时间 458 available = { 459 let mut ret = false; 460 for _ in 0..50 { 461 if let Ok(guard) = epoll.0.try_lock_irqsave() { 462 if guard.ep_events_available() { 463 ret = true; 464 break; 465 } 466 } 467 } 468 // 最后再次不使用try_lock尝试 469 if !ret { 470 ret = epoll.0.lock_irqsave().ep_events_available(); 471 } 472 ret 473 }; 474 475 if available { 476 continue; 477 } 478 479 // 如果有未处理的信号则返回错误 480 if current_pcb.sig_info_irqsave().sig_pending().signal().bits() != 0 { 481 return Err(SystemError::EINTR); 482 } 483 484 // 还未等待到事件发生,则睡眠 485 // 注册定时器 486 let mut timer = None; 487 if let Some(timespec) = timespec { 488 let handle = WakeUpHelper::new(current_pcb.clone()); 489 let jiffies = next_n_us_timer_jiffies( 490 (timespec.tv_sec * 1000000 + timespec.tv_nsec / 1000) as u64, 491 ); 492 let inner = Timer::new(handle, jiffies); 493 inner.activate(); 494 timer = Some(inner); 495 } 496 let guard = epoll.0.lock_irqsave(); 497 unsafe { guard.epoll_wq.sleep_without_schedule() }; 498 drop(guard); 499 schedule(SchedMode::SM_NONE); 500 // 被唤醒后,检查是否有事件可读 501 available = epoll.0.lock_irqsave().ep_events_available(); 502 if let Some(timer) = timer { 503 if timer.as_ref().timeout() { 504 // 超时 505 timeout = true; 506 } else { 507 // 未超时,则取消计时器 508 timer.cancel(); 509 } 510 } 511 } 512 } else { 513 panic!("An epoll file does not have the corresponding private information"); 514 } 515 } 516 517 /// ## 将已经准备好的事件拷贝到用户空间 518 /// 519 /// ### 参数 520 /// - epoll: 对应的epoll 521 /// - user_event: 用户空间传入的epoll_event地址,因为内存对其问题,所以这里需要直接操作地址 522 /// - max_events: 处理的最大事件数量 523 fn ep_send_events( 524 epoll: LockedEventPoll, 525 user_event: &mut [EPollEvent], 526 max_events: i32, 527 ) -> Result<usize, SystemError> { 528 let mut ep_guard = epoll.0.lock_irqsave(); 529 let mut res: usize = 0; 530 531 // 在水平触发模式下,需要将epitem再次加入队列,在下次循环再次判断是否还有事件 532 // (所以边缘触发的效率会高于水平触发,但是水平触发某些情况下能够使得更迅速地向用户反馈) 533 let mut push_back = Vec::new(); 534 while let Some(epitem) = ep_guard.ready_list.pop_front() { 535 if res >= max_events as usize { 536 push_back.push(epitem); 537 break; 538 } 539 let ep_events = EPollEventType::from_bits_truncate(epitem.event.read().events); 540 541 // 再次poll获取事件(为了防止水平触发一直加入队列) 542 let revents = epitem.ep_item_poll(); 543 if revents.is_empty() { 544 continue; 545 } 546 547 // 构建触发事件结构体 548 let event = EPollEvent { 549 events: revents.bits, 550 data: epitem.event.read().data, 551 }; 552 553 // 这里是需要判断下一个写入的位置是否为空指针 554 555 // TODO:这里有可能会出现事件丢失的情况 556 // 如果用户传入的数组长度小于传入的max_event,到这里时如果已经到数组最大长度,但是未到max_event 557 // 会出现的问题是我们会把这个数据写入到后面的内存中,用户无法在传入的数组中拿到事件,而且写脏数据到了后面一片内存,导致事件丢失 558 // 出现这个问题的几率比较小,首先是因为用户的使用不规范,后因为前面地址校验是按照max_event来校验的,只会在两块内存连着分配时出现,但是也是需要考虑的 559 560 // 以下的写法判断并无意义,只是记一下错误处理 561 // offset += core::mem::size_of::<EPollEvent>(); 562 // if offset >= max_offset { 563 // // 当前指向的地址已为空,则把epitem放回队列 564 // ep_guard.ready_list.push_back(epitem.clone()); 565 // if res == 0 { 566 // // 一个都未写入成功,表明用户传进的地址就是有问题的 567 // return Err(SystemError::EFAULT); 568 // } 569 // } 570 571 // 拷贝到用户空间 572 user_event[res] = event; 573 // 记数加一 574 res += 1; 575 576 // crate::debug!("ep send {event:?}"); 577 578 if ep_events.contains(EPollEventType::EPOLLONESHOT) { 579 let mut event_writer = epitem.event.write(); 580 let new_event = event_writer.events & EPollEventType::EP_PRIVATE_BITS.bits; 581 event_writer.set_events(new_event); 582 } else if !ep_events.contains(EPollEventType::EPOLLET) { 583 push_back.push(epitem); 584 } 585 } 586 587 for item in push_back { 588 ep_guard.ep_add_ready(item); 589 } 590 591 Ok(res) 592 } 593 594 // ### 查看文件是否为epoll文件 595 fn is_epoll_file(file: &Arc<File>) -> bool { 596 if let FilePrivateData::EPoll(_) = *file.private_data.lock() { 597 return true; 598 } 599 return false; 600 } 601 602 fn ep_insert( 603 epoll_guard: &mut SpinLockGuard<EventPoll>, 604 dst_file: Arc<File>, 605 epitem: Arc<EPollItem>, 606 ) -> Result<(), SystemError> { 607 if Self::is_epoll_file(&dst_file) { 608 return Err(SystemError::ENOSYS); 609 // TODO:现在的实现先不考虑嵌套其它类型的文件(暂时只针对socket),这里的嵌套指epoll/select/poll 610 } 611 612 let test_poll = dst_file.poll(); 613 if test_poll.is_err() && test_poll.unwrap_err() == SystemError::EOPNOTSUPP_OR_ENOTSUP { 614 // 如果目标文件不支持poll 615 return Err(SystemError::ENOSYS); 616 } 617 618 epoll_guard.ep_items.insert(epitem.fd, epitem.clone()); 619 620 // 检查文件是否已经有事件发生 621 let event = epitem.ep_item_poll(); 622 if !event.is_empty() { 623 // 加入到就绪队列 624 epoll_guard.ep_add_ready(epitem.clone()); 625 626 epoll_guard.ep_wake_one(); 627 } 628 629 // TODO: 嵌套epoll? 630 631 // 这个标志是用与电源管理相关,暂时不支持 632 if epitem.event.read().events & EPollEventType::EPOLLWAKEUP.bits() != 0 { 633 return Err(SystemError::ENOSYS); 634 } 635 636 dst_file.add_epoll(epitem.clone())?; 637 Ok(()) 638 } 639 640 pub fn ep_remove( 641 epoll: &mut SpinLockGuard<EventPoll>, 642 fd: i32, 643 dst_file: Option<Arc<File>>, 644 ) -> Result<(), SystemError> { 645 if let Some(dst_file) = dst_file { 646 dst_file.remove_epoll(epoll.self_ref.as_ref().unwrap())?; 647 } 648 649 let epitem = epoll.ep_items.remove(&fd).unwrap(); 650 651 let _ = epoll 652 .ready_list 653 .extract_if(|item| Arc::ptr_eq(item, &epitem)); 654 655 Ok(()) 656 } 657 658 /// ## 修改已经注册的监听事件 659 /// 660 /// ### 参数 661 /// - epoll_guard: EventPoll的锁 662 /// - epitem: 需要修改的描述符对应的epitem 663 /// - event: 新的事件 664 fn ep_modify( 665 epoll_guard: &mut SpinLockGuard<EventPoll>, 666 epitem: Arc<EPollItem>, 667 event: &EPollEvent, 668 ) -> Result<(), SystemError> { 669 let mut epi_event_guard = epitem.event.write(); 670 671 // 修改epitem 672 epi_event_guard.events = event.events; 673 epi_event_guard.data = event.data; 674 675 drop(epi_event_guard); 676 // 修改后检查文件是否已经有感兴趣事件发生 677 let event = epitem.ep_item_poll(); 678 if !event.is_empty() { 679 epoll_guard.ep_add_ready(epitem.clone()); 680 681 epoll_guard.ep_wake_one(); 682 } 683 // TODO:处理EPOLLWAKEUP,目前不支持 684 685 Ok(()) 686 } 687 688 /// ### 判断epoll是否有就绪item 689 pub fn ep_events_available(&self) -> bool { 690 !self.ready_list.is_empty() 691 } 692 693 /// ### 将epitem加入到就绪队列,如果为重复添加则忽略 694 pub fn ep_add_ready(&mut self, epitem: Arc<EPollItem>) { 695 let ret = self.ready_list.iter().find(|epi| Arc::ptr_eq(epi, &epitem)); 696 697 if ret.is_none() { 698 self.ready_list.push_back(epitem); 699 } 700 } 701 702 /// ### 判断该epoll上是否有进程在等待 703 pub fn ep_has_waiter(&self) -> bool { 704 self.epoll_wq.len() != 0 705 } 706 707 /// ### 唤醒所有在epoll上等待的进程 708 pub fn ep_wake_all(&self) { 709 self.epoll_wq.wakeup_all(None); 710 } 711 712 /// ### 唤醒所有在epoll上等待的首个进程 713 pub fn ep_wake_one(&self) { 714 self.epoll_wq.wakeup(None); 715 } 716 717 /// ### epoll的回调,支持epoll的文件有事件到来时直接调用该方法即可 718 pub fn wakeup_epoll( 719 epitems: &SpinLock<LinkedList<Arc<EPollItem>>>, 720 pollflags: EPollEventType, 721 ) -> Result<(), SystemError> { 722 let mut epitems_guard = epitems.try_lock_irqsave()?; 723 // 一次只取一个,因为一次也只有一个进程能拿到对应文件的 724 if let Some(epitem) = epitems_guard.pop_front() { 725 let epoll = epitem.epoll().upgrade().unwrap(); 726 let mut epoll_guard = epoll.try_lock()?; 727 let binding = epitem.clone(); 728 let event_guard = binding.event().read(); 729 let ep_events = EPollEventType::from_bits_truncate(event_guard.events()); 730 731 // 检查事件合理性以及是否有感兴趣的事件 732 if !(ep_events 733 .difference(EPollEventType::EP_PRIVATE_BITS) 734 .is_empty() 735 || pollflags.difference(ep_events).is_empty()) 736 { 737 // TODO: 未处理pm相关 738 739 // 首先将就绪的epitem加入等待队列 740 epoll_guard.ep_add_ready(epitem.clone()); 741 742 if epoll_guard.ep_has_waiter() { 743 if ep_events.contains(EPollEventType::EPOLLEXCLUSIVE) 744 && !pollflags.contains(EPollEventType::POLLFREE) 745 { 746 // 避免惊群 747 epoll_guard.ep_wake_one(); 748 } else { 749 epoll_guard.ep_wake_all(); 750 } 751 } 752 } 753 754 epitems_guard.push_back(epitem); 755 } 756 Ok(()) 757 } 758 } 759 760 /// 与C兼容的Epoll事件结构体 761 #[derive(Copy, Clone, Default)] 762 #[repr(packed)] 763 #[repr(C)] 764 pub struct EPollEvent { 765 /// 表示触发的事件 766 events: u32, 767 /// 内核态不使用该字段,该字段由用户态自由使用,在事件发生时内核将会原样返回 768 data: u64, 769 } 770 771 impl Debug for EPollEvent { 772 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 773 let events = self.events; 774 let u64 = self.data; 775 f.debug_struct("epoll_event") 776 .field("events", &events) 777 .field("data", &u64) 778 .finish() 779 } 780 } 781 782 impl EPollEvent { 783 pub fn set_events(&mut self, events: u32) { 784 self.events = events; 785 } 786 787 pub fn events(&self) -> u32 { 788 self.events 789 } 790 } 791 792 /// ## epoll_ctl函数的参数 793 #[derive(Debug, PartialEq)] 794 pub enum EPollCtlOption { 795 /// 注册新的文件描述符到epfd 796 Add, 797 /// 将对应的文件描述符从epfd中删除 798 Del, 799 /// 修改已经注册的文件描述符的监听事件 800 Mod, 801 } 802 803 impl EPollCtlOption { 804 pub fn from_op_num(op: usize) -> Result<Self, SystemError> { 805 match op { 806 1 => Ok(Self::Add), 807 2 => Ok(Self::Del), 808 3 => Ok(Self::Mod), 809 _ => Err(SystemError::EINVAL), 810 } 811 } 812 } 813 814 bitflags! { 815 #[allow(dead_code)] 816 pub struct EPollEventType: u32 { 817 /// 对应的描述符有新的数据可读时会触发 818 const EPOLLIN = 0x00000001; 819 /// 对应的描述符有紧急数据可读时会触发 820 const EPOLLPRI = 0x00000002; 821 /// 对应的描述符可以写入数据时会触发 822 const EPOLLOUT = 0x00000004; 823 /// 对应的描述符发生错误时会触发 824 const EPOLLERR = 0x00000008; 825 /// 对应的描述符被挂断(连接关闭)时会触发 826 const EPOLLHUP = 0x00000010; 827 /// 对应的描述符不是一个有效的文件描述符时会触发 828 const EPOLLNVAL = 0x00000020; 829 /// 普通数据可读,类似于`EPOLLIN` 830 const EPOLLRDNORM = 0x00000040; 831 /// 优先级带外数据可读 832 const EPOLLRDBAND = 0x00000080; 833 /// 普通数据可写,类似于'EPOLLOUT' 834 const EPOLLWRNORM = 0x00000100; 835 /// 优先级带外数据可写 836 const EPOLLWRBAND = 0x00000200; 837 /// 通过消息队列收到消息时会触 838 const EPOLLMSG = 0x00000400; 839 /// 对应的描述符被挂断(连接关闭)的一端发送了 FIN 时会触发(读关闭) 840 const EPOLLRDHUP = 0x00002000; 841 842 /// 以下为额外选项 843 /// 844 /// 特定选项,用于异步 I/O,目前未实现 845 const EPOLL_URING_WAKE = 1u32 << 27; 846 /// 设置epoll为独占模式 847 const EPOLLEXCLUSIVE = 1u32 << 28; 848 /// 允许在系统挂起时唤醒 epoll,通常用于通过 eventfd 或 timerfd 唤醒 epoll,(通常与电源管理相关,未实现) 849 const EPOLLWAKEUP = 1u32 << 29; 850 /// 表示只监听一次事件,之后需要重新添加 851 const EPOLLONESHOT = 1u32 << 30; 852 853 /// 启用边缘触发模式(即只有下次触发事件时才会通过epoll_wait返回), 854 /// 对应为水平触发(默认),水平触发模式下若这次未处理完数据,那epoll还会将其加入自己的就绪队列 855 const EPOLLET = 1u32 << 31; 856 857 /// 以下为组合码 858 const EPOLLINOUT_BITS = Self::EPOLLIN.bits | Self::EPOLLOUT.bits; 859 const EPOLLEXCLUSIVE_OK_BITS = 860 Self::EPOLLINOUT_BITS.bits 861 | Self::EPOLLERR.bits 862 | Self::EPOLLHUP.bits 863 | Self::EPOLLWAKEUP.bits 864 | Self::EPOLLET.bits 865 | Self::EPOLLEXCLUSIVE.bits; 866 867 const EP_PRIVATE_BITS = 868 Self::EPOLLWAKEUP.bits 869 | Self::EPOLLONESHOT.bits 870 | Self::EPOLLET.bits 871 | Self::EPOLLEXCLUSIVE.bits; 872 873 /// 表示epoll已经被释放,但是在目前的设计中未用到 874 const POLLFREE = 0x4000; 875 876 /// listen状态的socket可以接受连接 877 const EPOLL_LISTEN_CAN_ACCEPT = Self::EPOLLIN.bits | Self::EPOLLRDNORM.bits; 878 } 879 } 880