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