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