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