1 use core::sync::atomic::{AtomicUsize, Ordering}; 2 3 use alloc::{ 4 string::String, 5 sync::{Arc, Weak}, 6 vec::Vec, 7 }; 8 use kdepends::xarray::XArray; 9 use log::error; 10 use system_error::SystemError; 11 12 use super::{Dirent, FileType, IndexNode, InodeId, Metadata, SpecialNodeData}; 13 use crate::filesystem::eventfd::EventFdInode; 14 use crate::libs::lazy_init::Lazy; 15 use crate::perf::PerfEventInode; 16 use crate::{ 17 arch::MMArch, 18 driver::{ 19 base::{block::SeekFrom, device::DevicePrivateData}, 20 tty::tty_device::TtyFilePrivateData, 21 }, 22 filesystem::procfs::ProcfsFilePrivateData, 23 ipc::pipe::{LockedPipeInode, PipeFsPrivateData}, 24 libs::{rwlock::RwLock, spinlock::SpinLock}, 25 mm::{page::Page, MemoryManagementArch}, 26 net::{ 27 event_poll::{EPollItem, EPollPrivateData, EventPoll}, 28 socket::SocketInode, 29 }, 30 process::{cred::Cred, ProcessManager}, 31 }; 32 33 /// 文件私有信息的枚举类型 34 #[derive(Debug, Clone)] 35 #[allow(dead_code)] 36 pub enum FilePrivateData { 37 /// 管道文件私有信息 38 Pipefs(PipeFsPrivateData), 39 /// procfs文件私有信息 40 Procfs(ProcfsFilePrivateData), 41 /// 设备文件的私有信息 42 DevFS(DevicePrivateData), 43 /// tty设备文件的私有信息 44 Tty(TtyFilePrivateData), 45 /// epoll私有信息 46 EPoll(EPollPrivateData), 47 /// 不需要文件私有信息 48 Unused, 49 } 50 51 impl Default for FilePrivateData { 52 fn default() -> Self { 53 return Self::Unused; 54 } 55 } 56 57 impl FilePrivateData { 58 pub fn update_mode(&mut self, mode: FileMode) { 59 if let FilePrivateData::Pipefs(pdata) = self { 60 pdata.set_mode(mode); 61 } 62 } 63 } 64 65 bitflags! { 66 /// @brief 文件打开模式 67 /// 其中,低2bit组合而成的数字的值,用于表示访问权限。其他的bit,才支持通过按位或的方式来表示参数 68 /// 69 /// 与Linux 5.19.10的uapi/asm-generic/fcntl.h相同 70 /// https://code.dragonos.org.cn/xref/linux-5.19.10/tools/include/uapi/asm-generic/fcntl.h#19 71 #[allow(clippy::bad_bit_mask)] 72 pub struct FileMode: u32{ 73 /* File access modes for `open' and `fcntl'. */ 74 /// Open Read-only 75 const O_RDONLY = 0o0; 76 /// Open Write-only 77 const O_WRONLY = 0o1; 78 /// Open read/write 79 const O_RDWR = 0o2; 80 /// Mask for file access modes 81 const O_ACCMODE = 0o00000003; 82 83 /* Bits OR'd into the second argument to open. */ 84 /// Create file if it does not exist 85 const O_CREAT = 0o00000100; 86 /// Fail if file already exists 87 const O_EXCL = 0o00000200; 88 /// Do not assign controlling terminal 89 const O_NOCTTY = 0o00000400; 90 /// 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空 91 const O_TRUNC = 0o00001000; 92 /// 文件指针会被移动到文件末尾 93 const O_APPEND = 0o00002000; 94 /// 非阻塞式IO模式 95 const O_NONBLOCK = 0o00004000; 96 /// 每次write都等待物理I/O完成,但是如果写操作不影响读取刚写入的数据,则不等待文件属性更新 97 const O_DSYNC = 0o00010000; 98 /// fcntl, for BSD compatibility 99 const FASYNC = 0o00020000; 100 /* direct disk access hint */ 101 const O_DIRECT = 0o00040000; 102 const O_LARGEFILE = 0o00100000; 103 /// 打开的必须是一个目录 104 const O_DIRECTORY = 0o00200000; 105 /// Do not follow symbolic links 106 const O_NOFOLLOW = 0o00400000; 107 const O_NOATIME = 0o01000000; 108 /// set close_on_exec 109 const O_CLOEXEC = 0o02000000; 110 /// 每次write都等到物理I/O完成,包括write引起的文件属性的更新 111 const O_SYNC = 0o04000000; 112 113 const O_PATH = 0o10000000; 114 115 const O_PATH_FLAGS = Self::O_DIRECTORY.bits|Self::O_NOFOLLOW.bits|Self::O_CLOEXEC.bits|Self::O_PATH.bits; 116 } 117 } 118 119 impl FileMode { 120 /// @brief 获取文件的访问模式的值 121 #[inline] 122 pub fn accmode(&self) -> u32 { 123 return self.bits() & FileMode::O_ACCMODE.bits(); 124 } 125 } 126 127 /// 页面缓存 128 pub struct PageCache { 129 xarray: SpinLock<XArray<Arc<Page>>>, 130 inode: Lazy<Weak<dyn IndexNode>>, 131 } 132 133 impl core::fmt::Debug for PageCache { 134 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 135 f.debug_struct("PageCache") 136 .field( 137 "xarray", 138 &self 139 .xarray 140 .lock() 141 .range(0..((MMArch::PAGE_ADDRESS_SIZE >> MMArch::PAGE_SHIFT) as u64)) 142 .map(|(_, r)| (*r).clone()) 143 .collect::<Vec<Arc<Page>>>(), 144 ) 145 .finish() 146 } 147 } 148 149 impl PageCache { 150 pub fn new(inode: Option<Weak<dyn IndexNode>>) -> Arc<PageCache> { 151 let page_cache = Self { 152 xarray: SpinLock::new(XArray::new()), 153 inode: { 154 let v: Lazy<Weak<dyn IndexNode>> = Lazy::new(); 155 if let Some(inode) = inode { 156 v.init(inode); 157 } 158 v 159 }, 160 }; 161 Arc::new(page_cache) 162 } 163 164 pub fn inode(&self) -> Option<Weak<dyn IndexNode>> { 165 self.inode.try_get().cloned() 166 } 167 168 pub fn add_page(&self, offset: usize, page: &Arc<Page>) { 169 let mut guard = self.xarray.lock(); 170 let mut cursor = guard.cursor_mut(offset as u64); 171 cursor.store(page.clone()); 172 } 173 174 pub fn get_page(&self, offset: usize) -> Option<Arc<Page>> { 175 let mut guard = self.xarray.lock(); 176 let mut cursor = guard.cursor_mut(offset as u64); 177 let page = cursor.load().map(|r| (*r).clone()); 178 page 179 } 180 181 pub fn remove_page(&self, offset: usize) { 182 let mut guard = self.xarray.lock(); 183 let mut cursor = guard.cursor_mut(offset as u64); 184 cursor.remove(); 185 } 186 187 pub fn set_inode(&self, inode: Weak<dyn IndexNode>) -> Result<(), SystemError> { 188 if self.inode.initialized() { 189 return Err(SystemError::EINVAL); 190 } 191 self.inode.init(inode); 192 Ok(()) 193 } 194 } 195 196 /// @brief 抽象文件结构体 197 #[derive(Debug)] 198 pub struct File { 199 inode: Arc<dyn IndexNode>, 200 /// 对于文件,表示字节偏移量;对于文件夹,表示当前操作的子目录项偏移量 201 offset: AtomicUsize, 202 /// 文件的打开模式 203 mode: RwLock<FileMode>, 204 /// 文件类型 205 file_type: FileType, 206 /// readdir时候用的,暂存的本次循环中,所有子目录项的名字的数组 207 readdir_subdirs_name: SpinLock<Vec<String>>, 208 pub private_data: SpinLock<FilePrivateData>, 209 /// 文件的凭证 210 cred: Cred, 211 } 212 213 impl File { 214 /// @brief 创建一个新的文件对象 215 /// 216 /// @param inode 文件对象对应的inode 217 /// @param mode 文件的打开模式 218 pub fn new(inode: Arc<dyn IndexNode>, mode: FileMode) -> Result<Self, SystemError> { 219 let mut inode = inode; 220 let file_type = inode.metadata()?.file_type; 221 if file_type == FileType::Pipe { 222 if let Some(SpecialNodeData::Pipe(pipe_inode)) = inode.special_node() { 223 inode = pipe_inode; 224 } 225 } 226 227 let f = File { 228 inode, 229 offset: AtomicUsize::new(0), 230 mode: RwLock::new(mode), 231 file_type, 232 readdir_subdirs_name: SpinLock::new(Vec::default()), 233 private_data: SpinLock::new(FilePrivateData::default()), 234 cred: ProcessManager::current_pcb().cred(), 235 }; 236 f.inode.open(f.private_data.lock(), &mode)?; 237 238 return Ok(f); 239 } 240 241 /// @brief 从文件中读取指定的字节数到buffer中 242 /// 243 /// @param len 要读取的字节数 244 /// @param buf 目标buffer 245 /// 246 /// @return Ok(usize) 成功读取的字节数 247 /// @return Err(SystemError) 错误码 248 pub fn read(&self, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> { 249 self.do_read( 250 self.offset.load(core::sync::atomic::Ordering::SeqCst), 251 len, 252 buf, 253 true, 254 ) 255 } 256 257 /// @brief 从buffer向文件写入指定的字节数的数据 258 /// 259 /// @param len 要写入的字节数 260 /// @param buf 源数据buffer 261 /// 262 /// @return Ok(usize) 成功写入的字节数 263 /// @return Err(SystemError) 错误码 264 pub fn write(&self, len: usize, buf: &[u8]) -> Result<usize, SystemError> { 265 self.do_write( 266 self.offset.load(core::sync::atomic::Ordering::SeqCst), 267 len, 268 buf, 269 true, 270 ) 271 } 272 273 /// ## 从文件中指定的偏移处读取指定的字节数到buf中 274 /// 275 /// ### 参数 276 /// - `offset`: 文件偏移量 277 /// - `len`: 要读取的字节数 278 /// - `buf`: 读出缓冲区 279 /// 280 /// ### 返回值 281 /// - `Ok(usize)`: 成功读取的字节数 282 pub fn pread(&self, offset: usize, len: usize, buf: &mut [u8]) -> Result<usize, SystemError> { 283 self.do_read(offset, len, buf, false) 284 } 285 286 /// ## 从buf向文件中指定的偏移处写入指定的字节数的数据 287 /// 288 /// ### 参数 289 /// - `offset`: 文件偏移量 290 /// - `len`: 要写入的字节数 291 /// - `buf`: 写入缓冲区 292 /// 293 /// ### 返回值 294 /// - `Ok(usize)`: 成功写入的字节数 295 pub fn pwrite(&self, offset: usize, len: usize, buf: &[u8]) -> Result<usize, SystemError> { 296 self.do_write(offset, len, buf, false) 297 } 298 299 fn do_read( 300 &self, 301 offset: usize, 302 len: usize, 303 buf: &mut [u8], 304 update_offset: bool, 305 ) -> Result<usize, SystemError> { 306 // 先检查本文件在权限等规则下,是否可读取。 307 self.readable()?; 308 if buf.len() < len { 309 return Err(SystemError::ENOBUFS); 310 } 311 312 let len = self 313 .inode 314 .read_at(offset, len, buf, self.private_data.lock()) 315 .map_err(|e| { 316 if e == SystemError::ERESTARTSYS { 317 SystemError::EINTR 318 } else { 319 e 320 } 321 })?; 322 323 if update_offset { 324 self.offset 325 .fetch_add(len, core::sync::atomic::Ordering::SeqCst); 326 } 327 328 Ok(len) 329 } 330 331 fn do_write( 332 &self, 333 offset: usize, 334 len: usize, 335 buf: &[u8], 336 update_offset: bool, 337 ) -> Result<usize, SystemError> { 338 // 先检查本文件在权限等规则下,是否可写入。 339 self.writeable()?; 340 if buf.len() < len { 341 return Err(SystemError::ENOBUFS); 342 } 343 344 // 如果文件指针已经超过了文件大小,则需要扩展文件大小 345 if offset > self.inode.metadata()?.size as usize { 346 self.inode.resize(offset).map_err(|e| { 347 if e == SystemError::ERESTARTSYS { 348 SystemError::EINTR 349 } else { 350 e 351 } 352 })?; 353 } 354 let len = self 355 .inode 356 .write_at(offset, len, buf, self.private_data.lock()) 357 .map_err(|e| { 358 if e == SystemError::ERESTARTSYS { 359 SystemError::EINTR 360 } else { 361 e 362 } 363 })?; 364 365 if update_offset { 366 self.offset 367 .fetch_add(len, core::sync::atomic::Ordering::SeqCst); 368 } 369 370 Ok(len) 371 } 372 373 /// @brief 获取文件的元数据 374 pub fn metadata(&self) -> Result<Metadata, SystemError> { 375 return self.inode.metadata(); 376 } 377 378 /// @brief 根据inode号获取子目录项的名字 379 #[allow(dead_code)] 380 pub fn get_entry_name(&self, ino: InodeId) -> Result<String, SystemError> { 381 return self.inode.get_entry_name(ino); 382 } 383 384 /// @brief 调整文件操作指针的位置 385 /// 386 /// @param origin 调整的起始位置 387 pub fn lseek(&self, origin: SeekFrom) -> Result<usize, SystemError> { 388 let file_type = self.inode.metadata()?.file_type; 389 match file_type { 390 FileType::Pipe | FileType::CharDevice => { 391 return Err(SystemError::ESPIPE); 392 } 393 _ => {} 394 } 395 396 let pos: i64 = match origin { 397 SeekFrom::SeekSet(offset) => offset, 398 SeekFrom::SeekCurrent(offset) => self.offset.load(Ordering::SeqCst) as i64 + offset, 399 SeekFrom::SeekEnd(offset) => { 400 let metadata = self.metadata()?; 401 metadata.size + offset 402 } 403 SeekFrom::Invalid => { 404 return Err(SystemError::EINVAL); 405 } 406 }; 407 // 根据linux man page, lseek允许超出文件末尾,并且不改变文件大小 408 // 当pos超出文件末尾时,read返回0。直到开始写入数据时,才会改变文件大小 409 if pos < 0 { 410 return Err(SystemError::EOVERFLOW); 411 } 412 self.offset.store(pos as usize, Ordering::SeqCst); 413 return Ok(pos as usize); 414 } 415 416 /// @brief 判断当前文件是否可读 417 #[inline] 418 pub fn readable(&self) -> Result<(), SystemError> { 419 // 暂时认为只要不是write only, 就可读 420 if *self.mode.read() == FileMode::O_WRONLY { 421 return Err(SystemError::EPERM); 422 } 423 424 return Ok(()); 425 } 426 427 /// @brief 判断当前文件是否可写 428 #[inline] 429 pub fn writeable(&self) -> Result<(), SystemError> { 430 // 暂时认为只要不是read only, 就可写 431 if *self.mode.read() == FileMode::O_RDONLY { 432 return Err(SystemError::EPERM); 433 } 434 435 return Ok(()); 436 } 437 438 /// @biref 充填dirent结构体 439 /// @return 返回dirent结构体的大小 440 pub fn readdir(&self, dirent: &mut Dirent) -> Result<u64, SystemError> { 441 let inode: &Arc<dyn IndexNode> = &self.inode; 442 let mut readdir_subdirs_name = self.readdir_subdirs_name.lock(); 443 let offset = self.offset.load(Ordering::SeqCst); 444 // 如果偏移量为0 445 if offset == 0 { 446 // 通过list更新readdir_subdirs_name 447 *readdir_subdirs_name = inode.list()?; 448 readdir_subdirs_name.sort(); 449 } 450 // debug!("sub_entries={sub_entries:?}"); 451 452 // 已经读到末尾 453 if offset == readdir_subdirs_name.len() { 454 self.offset.store(0, Ordering::SeqCst); 455 return Ok(0); 456 } 457 let name = &readdir_subdirs_name[offset]; 458 let sub_inode: Arc<dyn IndexNode> = match inode.find(name) { 459 Ok(i) => i, 460 Err(e) => { 461 error!( 462 "Readdir error: Failed to find sub inode:{name:?}, file={self:?}, error={e:?}" 463 ); 464 return Err(e); 465 } 466 }; 467 468 let name_bytes: &[u8] = name.as_bytes(); 469 470 // 根据posix的规定,dirent中的d_name是一个不定长的数组,因此需要unsafe来拷贝数据 471 unsafe { 472 let ptr = &mut dirent.d_name as *mut u8; 473 474 let buf: &mut [u8] = 475 ::core::slice::from_raw_parts_mut::<'static, u8>(ptr, name_bytes.len() + 1); 476 buf[0..name_bytes.len()].copy_from_slice(name_bytes); 477 buf[name_bytes.len()] = 0; 478 } 479 480 self.offset.fetch_add(1, Ordering::SeqCst); 481 dirent.d_ino = sub_inode.metadata().unwrap().inode_id.into() as u64; 482 dirent.d_type = sub_inode.metadata().unwrap().file_type.get_file_type_num() as u8; 483 484 // 计算dirent结构体的大小 485 let size = (name_bytes.len() + ::core::mem::size_of::<Dirent>() 486 - ::core::mem::size_of_val(&dirent.d_name)) as u64; 487 488 dirent.d_reclen = size as u16; 489 dirent.d_off += dirent.d_reclen as i64; 490 491 return Ok(size); 492 } 493 494 pub fn inode(&self) -> Arc<dyn IndexNode> { 495 return self.inode.clone(); 496 } 497 498 /// @brief 尝试克隆一个文件 499 /// 500 /// @return Option<File> 克隆后的文件结构体。如果克隆失败,返回None 501 pub fn try_clone(&self) -> Option<File> { 502 let res = Self { 503 inode: self.inode.clone(), 504 offset: AtomicUsize::new(self.offset.load(Ordering::SeqCst)), 505 mode: RwLock::new(self.mode()), 506 file_type: self.file_type, 507 readdir_subdirs_name: SpinLock::new(self.readdir_subdirs_name.lock().clone()), 508 private_data: SpinLock::new(self.private_data.lock().clone()), 509 cred: self.cred.clone(), 510 }; 511 // 调用inode的open方法,让inode知道有新的文件打开了这个inode 512 if self 513 .inode 514 .open(res.private_data.lock(), &res.mode()) 515 .is_err() 516 { 517 return None; 518 } 519 520 return Some(res); 521 } 522 523 /// @brief 获取文件的类型 524 #[inline] 525 pub fn file_type(&self) -> FileType { 526 return self.file_type; 527 } 528 529 /// @brief 获取文件的打开模式 530 #[inline] 531 pub fn mode(&self) -> FileMode { 532 return *self.mode.read(); 533 } 534 535 /// 获取文件是否在execve时关闭 536 #[inline] 537 pub fn close_on_exec(&self) -> bool { 538 return self.mode().contains(FileMode::O_CLOEXEC); 539 } 540 541 /// 设置文件是否在execve时关闭 542 #[inline] 543 pub fn set_close_on_exec(&self, close_on_exec: bool) { 544 let mut mode_guard = self.mode.write(); 545 if close_on_exec { 546 mode_guard.insert(FileMode::O_CLOEXEC); 547 } else { 548 mode_guard.remove(FileMode::O_CLOEXEC); 549 } 550 } 551 552 pub fn set_mode(&self, mode: FileMode) -> Result<(), SystemError> { 553 // todo: 是否需要调用inode的open方法,以更新private data(假如它与mode有关的话)? 554 // 也许需要加个更好的设计,让inode知晓文件的打开模式发生了变化,让它自己决定是否需要更新private data 555 556 // 直接修改文件的打开模式 557 *self.mode.write() = mode; 558 self.private_data.lock().update_mode(mode); 559 return Ok(()); 560 } 561 562 /// @brief 重新设置文件的大小 563 /// 564 /// 如果文件大小增加,则文件内容不变,但是文件的空洞部分会被填充为0 565 /// 如果文件大小减小,则文件内容会被截断 566 /// 567 /// @return 成功:Ok() 568 /// 失败:Err(错误码) 569 pub fn ftruncate(&self, len: usize) -> Result<(), SystemError> { 570 // 如果文件不可写,返回错误 571 self.writeable()?; 572 573 // 调用inode的truncate方法 574 self.inode.resize(len)?; 575 return Ok(()); 576 } 577 578 /// ## 向该文件添加一个EPollItem对象 579 /// 580 /// 在文件状态发生变化时,需要向epoll通知 581 pub fn add_epoll(&self, epitem: Arc<EPollItem>) -> Result<(), SystemError> { 582 match self.file_type { 583 FileType::Socket => { 584 let inode = self.inode.downcast_ref::<SocketInode>().unwrap(); 585 let mut socket = inode.inner(); 586 587 return socket.add_epoll(epitem); 588 } 589 FileType::Pipe => { 590 let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap(); 591 return inode.inner().lock().add_epoll(epitem); 592 } 593 _ => { 594 let r = self.inode.kernel_ioctl(epitem, &self.private_data.lock()); 595 if r.is_err() { 596 return Err(SystemError::ENOSYS); 597 } 598 599 Ok(()) 600 } 601 } 602 } 603 604 /// ## 删除一个绑定的epoll 605 pub fn remove_epoll(&self, epoll: &Weak<SpinLock<EventPoll>>) -> Result<(), SystemError> { 606 match self.file_type { 607 FileType::Socket => { 608 let inode = self.inode.downcast_ref::<SocketInode>().unwrap(); 609 let mut socket = inode.inner(); 610 611 socket.remove_epoll(epoll) 612 } 613 FileType::Pipe => { 614 let inode = self.inode.downcast_ref::<LockedPipeInode>().unwrap(); 615 inode.inner().lock().remove_epoll(epoll) 616 } 617 _ => { 618 let inode = self.inode.downcast_ref::<EventFdInode>(); 619 if let Some(inode) = inode { 620 return inode.remove_epoll(epoll); 621 } 622 let inode = self 623 .inode 624 .downcast_ref::<PerfEventInode>() 625 .ok_or(SystemError::ENOSYS)?; 626 return inode.remove_epoll(epoll); 627 } 628 } 629 } 630 631 pub fn poll(&self) -> Result<usize, SystemError> { 632 self.inode.poll(&self.private_data.lock()) 633 } 634 } 635 636 impl Drop for File { 637 fn drop(&mut self) { 638 let r: Result<(), SystemError> = self.inode.close(self.private_data.lock()); 639 // 打印错误信息 640 if r.is_err() { 641 error!( 642 "pid: {:?} failed to close file: {:?}, errno={:?}", 643 ProcessManager::current_pcb().pid(), 644 self, 645 r.as_ref().unwrap_err() 646 ); 647 } 648 } 649 } 650 651 /// @brief pcb里面的文件描述符数组 652 #[derive(Debug)] 653 pub struct FileDescriptorVec { 654 /// 当前进程打开的文件描述符 655 fds: Vec<Option<Arc<File>>>, 656 } 657 impl Default for FileDescriptorVec { 658 fn default() -> Self { 659 Self::new() 660 } 661 } 662 impl FileDescriptorVec { 663 pub const PROCESS_MAX_FD: usize = 1024; 664 665 #[inline(never)] 666 pub fn new() -> FileDescriptorVec { 667 let mut data = Vec::with_capacity(FileDescriptorVec::PROCESS_MAX_FD); 668 data.resize(FileDescriptorVec::PROCESS_MAX_FD, None); 669 670 // 初始化文件描述符数组结构体 671 return FileDescriptorVec { fds: data }; 672 } 673 674 /// @brief 克隆一个文件描述符数组 675 /// 676 /// @return FileDescriptorVec 克隆后的文件描述符数组 677 pub fn clone(&self) -> FileDescriptorVec { 678 let mut res = FileDescriptorVec::new(); 679 for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 680 if let Some(file) = &self.fds[i] { 681 if let Some(file) = file.try_clone() { 682 res.fds[i] = Some(Arc::new(file)); 683 } 684 } 685 } 686 return res; 687 } 688 689 /// 返回 `已经打开的` 文件描述符的数量 690 pub fn fd_open_count(&self) -> usize { 691 let mut size = 0; 692 for fd in &self.fds { 693 if fd.is_some() { 694 size += 1; 695 } 696 } 697 return size; 698 } 699 700 /// @brief 判断文件描述符序号是否合法 701 /// 702 /// @return true 合法 703 /// 704 /// @return false 不合法 705 #[inline] 706 pub fn validate_fd(fd: i32) -> bool { 707 return !(fd < 0 || fd as usize > FileDescriptorVec::PROCESS_MAX_FD); 708 } 709 710 /// 申请文件描述符,并把文件对象存入其中。 711 /// 712 /// ## 参数 713 /// 714 /// - `file` 要存放的文件对象 715 /// - `fd` 如果为Some(i32),表示指定要申请这个文件描述符,如果这个文件描述符已经被使用,那么返回EBADF 716 /// 717 /// ## 返回值 718 /// 719 /// - `Ok(i32)` 申请成功,返回申请到的文件描述符 720 /// - `Err(SystemError)` 申请失败,返回错误码,并且,file对象将被drop掉 721 pub fn alloc_fd(&mut self, file: File, fd: Option<i32>) -> Result<i32, SystemError> { 722 if let Some(new_fd) = fd { 723 let x = &mut self.fds[new_fd as usize]; 724 if x.is_none() { 725 *x = Some(Arc::new(file)); 726 return Ok(new_fd); 727 } else { 728 return Err(SystemError::EBADF); 729 } 730 } else { 731 // 没有指定要申请的文件描述符编号 732 for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 733 if self.fds[i].is_none() { 734 self.fds[i] = Some(Arc::new(file)); 735 return Ok(i as i32); 736 } 737 } 738 return Err(SystemError::EMFILE); 739 } 740 } 741 742 /// 根据文件描述符序号,获取文件结构体的Arc指针 743 /// 744 /// ## 参数 745 /// 746 /// - `fd` 文件描述符序号 747 pub fn get_file_by_fd(&self, fd: i32) -> Option<Arc<File>> { 748 if !FileDescriptorVec::validate_fd(fd) { 749 return None; 750 } 751 self.fds[fd as usize].clone() 752 } 753 754 /// 释放文件描述符,同时关闭文件。 755 /// 756 /// ## 参数 757 /// 758 /// - `fd` 文件描述符序号 759 pub fn drop_fd(&mut self, fd: i32) -> Result<Arc<File>, SystemError> { 760 self.get_file_by_fd(fd).ok_or(SystemError::EBADF)?; 761 762 // 把文件描述符数组对应位置设置为空 763 let file = self.fds[fd as usize].take().unwrap(); 764 return Ok(file); 765 } 766 767 #[allow(dead_code)] 768 pub fn iter(&self) -> FileDescriptorIterator { 769 return FileDescriptorIterator::new(self); 770 } 771 772 pub fn close_on_exec(&mut self) { 773 for i in 0..FileDescriptorVec::PROCESS_MAX_FD { 774 if let Some(file) = &self.fds[i] { 775 let to_drop = file.close_on_exec(); 776 if to_drop { 777 if let Err(r) = self.drop_fd(i as i32) { 778 error!( 779 "Failed to close file: pid = {:?}, fd = {}, error = {:?}", 780 ProcessManager::current_pcb().pid(), 781 i, 782 r 783 ); 784 } 785 } 786 } 787 } 788 } 789 } 790 791 #[derive(Debug)] 792 pub struct FileDescriptorIterator<'a> { 793 fds: &'a FileDescriptorVec, 794 index: usize, 795 } 796 797 impl<'a> FileDescriptorIterator<'a> { 798 pub fn new(fds: &'a FileDescriptorVec) -> Self { 799 return Self { fds, index: 0 }; 800 } 801 } 802 803 impl<'a> Iterator for FileDescriptorIterator<'a> { 804 type Item = (i32, Arc<File>); 805 806 fn next(&mut self) -> Option<Self::Item> { 807 while self.index < FileDescriptorVec::PROCESS_MAX_FD { 808 let fd = self.index as i32; 809 self.index += 1; 810 if let Some(file) = self.fds.get_file_by_fd(fd) { 811 return Some((fd, file)); 812 } 813 } 814 return None; 815 } 816 } 817