Skip to content

Commit

Permalink
socket统一改用GlobalSocketHandle,并且修复fcntl SETFD的错误 (DragonOS-Community…
Browse files Browse the repository at this point in the history
…#730)

* socket统一改用`GlobalSocketHandle`,并且修复fcntl SETFD的错误

---------

Co-authored-by: longjin <[email protected]>
  • Loading branch information
2 people authored and BrahmaMantra committed Dec 9, 2024
1 parent f3345ed commit f25a9f5
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 154 deletions.
2 changes: 1 addition & 1 deletion kernel/src/arch/x86_64/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub extern "sysv64" fn syscall_handler(frame: &mut TrapFrame) {
mfence();
let pid = ProcessManager::current_pcb().pid();
let show = false;
// let show = if syscall_num != SYS_SCHED && pid.data() > 3 {
// let show = if syscall_num != SYS_SCHED && pid.data() >= 7 {
// true
// } else {
// false
Expand Down
38 changes: 32 additions & 6 deletions kernel/src/filesystem/vfs/syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1024,6 +1024,15 @@ impl Syscall {
oldfd: i32,
newfd: i32,
fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
) -> Result<usize, SystemError> {
Self::do_dup3(oldfd, newfd, FileMode::empty(), fd_table_guard)
}

fn do_dup3(
oldfd: i32,
newfd: i32,
flags: FileMode,
fd_table_guard: &mut RwLockWriteGuard<'_, FileDescriptorVec>,
) -> Result<usize, SystemError> {
// 确认oldfd, newid是否有效
if !(FileDescriptorVec::validate_fd(oldfd) && FileDescriptorVec::validate_fd(newfd)) {
Expand All @@ -1047,8 +1056,12 @@ impl Syscall {
.get_file_by_fd(oldfd)
.ok_or(SystemError::EBADF)?;
let new_file = old_file.try_clone().ok_or(SystemError::EBADF)?;
// dup2默认非cloexec
new_file.set_close_on_exec(false);

if flags.contains(FileMode::O_CLOEXEC) {
new_file.set_close_on_exec(true);
} else {
new_file.set_close_on_exec(false);
}
// 申请文件描述符,并把文件对象存入其中
let res = fd_table_guard
.alloc_fd(new_file, Some(newfd))
Expand All @@ -1064,8 +1077,9 @@ impl Syscall {
/// - `cmd`:命令
/// - `arg`:参数
pub fn fcntl(fd: i32, cmd: FcntlCommand, arg: i32) -> Result<usize, SystemError> {
// kdebug!("fcntl ({cmd:?}) fd: {fd}, arg={arg}");
match cmd {
FcntlCommand::DupFd => {
FcntlCommand::DupFd | FcntlCommand::DupFdCloexec => {
if arg < 0 || arg as usize >= FileDescriptorVec::PROCESS_MAX_FD {
return Err(SystemError::EBADF);
}
Expand All @@ -1074,7 +1088,16 @@ impl Syscall {
let binding = ProcessManager::current_pcb().fd_table();
let mut fd_table_guard = binding.write();
if fd_table_guard.get_file_by_fd(i as i32).is_none() {
return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
if cmd == FcntlCommand::DupFd {
return Self::do_dup2(fd, i as i32, &mut fd_table_guard);
} else {
return Self::do_dup3(
fd,
i as i32,
FileMode::O_CLOEXEC,
&mut fd_table_guard,
);
}
}
}
return Err(SystemError::EMFILE);
Expand All @@ -1083,12 +1106,15 @@ impl Syscall {
// Get file descriptor flags.
let binding = ProcessManager::current_pcb().fd_table();
let fd_table_guard = binding.read();

if let Some(file) = fd_table_guard.get_file_by_fd(fd) {
// drop guard 以避免无法调度的问题
drop(fd_table_guard);

if file.close_on_exec() {
return Ok(FD_CLOEXEC as usize);
} else {
return Ok(0);
}
}
return Err(SystemError::EBADF);
Expand Down Expand Up @@ -1145,8 +1171,8 @@ impl Syscall {
// TODO: unimplemented
// 未实现的命令,返回0,不报错。

// kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
return Ok(0);
kwarn!("fcntl: unimplemented command: {:?}, defaults to 0.", cmd);
return Err(SystemError::ENOSYS);
}
}
}
Expand Down
11 changes: 6 additions & 5 deletions kernel/src/net/net_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{

use super::{
event_poll::{EPollEventType, EventPoll},
socket::{inet::TcpSocket, HANDLE_MAP, SOCKET_SET},
socket::{handle::GlobalSocketHandle, inet::TcpSocket, HANDLE_MAP, SOCKET_SET},
};

/// The network poll function, which will be called by timer.
Expand Down Expand Up @@ -188,7 +188,8 @@ pub fn poll_ifaces_try_lock_onetime() -> Result<(), SystemError> {
fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
for (handle, socket_type) in sockets.iter() {
let handle_guard = HANDLE_MAP.read_irqsave();
let item = handle_guard.get(&handle);
let global_handle = GlobalSocketHandle::new_smoltcp_handle(handle);
let item = handle_guard.get(&global_handle);
if item.is_none() {
continue;
}
Expand All @@ -203,7 +204,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
match socket_type {
smoltcp::socket::Socket::Raw(_) | smoltcp::socket::Socket::Udp(_) => {
handle_guard
.get(&handle)
.get(&global_handle)
.unwrap()
.wait_queue
.wakeup_any(events);
Expand All @@ -217,7 +218,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
events |= TcpSocket::CAN_CONNECT;
}
handle_guard
.get(&handle)
.get(&global_handle)
.unwrap()
.wait_queue
.wakeup_any(events);
Expand All @@ -227,7 +228,7 @@ fn send_event(sockets: &smoltcp::iface::SocketSet) -> Result<(), SystemError> {
}
drop(handle_guard);
let mut handle_guard = HANDLE_MAP.write_irqsave();
let handle_item = handle_guard.get_mut(&handle).unwrap();
let handle_item = handle_guard.get_mut(&global_handle).unwrap();
EventPoll::wakeup_epoll(
&handle_item.epitems,
EPollEventType::from_bits_truncate(events as u32),
Expand Down
39 changes: 39 additions & 0 deletions kernel/src/net/socket/handle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
use ida::IdAllocator;
use smoltcp::iface::SocketHandle;

int_like!(KernelHandle, usize);

/// # socket的句柄管理组件
/// 它在smoltcp的SocketHandle上封装了一层,增加更多的功能。
/// 比如,在socket被关闭时,自动释放socket的资源,通知系统的其他组件。
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy)]
pub enum GlobalSocketHandle {
Smoltcp(SocketHandle),
Kernel(KernelHandle),
}

static KERNEL_HANDLE_IDA: IdAllocator = IdAllocator::new(0, usize::MAX);

impl GlobalSocketHandle {
pub fn new_smoltcp_handle(handle: SocketHandle) -> Self {
return Self::Smoltcp(handle);
}

pub fn new_kernel_handle() -> Self {
return Self::Kernel(KernelHandle::new(KERNEL_HANDLE_IDA.alloc().unwrap()));
}

pub fn smoltcp_handle(&self) -> Option<SocketHandle> {
if let Self::Smoltcp(sh) = *self {
return Some(sh);
}
None
}

pub fn kernel_handle(&self) -> Option<KernelHandle> {
if let Self::Kernel(kh) = *self {
return Some(kh);
}
None
}
}
Loading

0 comments on commit f25a9f5

Please sign in to comment.