diff --git a/kernel/src/net/syscall.rs b/kernel/src/net/syscall.rs index 4b267339..9a0980aa 100644 --- a/kernel/src/net/syscall.rs +++ b/kernel/src/net/syscall.rs @@ -21,6 +21,10 @@ use super::{ Endpoint, Protocol, ShutdownType, Socket, }; +/// Flags for socket, socketpair, accept4 +const SOCK_CLOEXEC: FileMode = FileMode::O_CLOEXEC; +const SOCK_NONBLOCK: FileMode = FileMode::O_NONBLOCK; + impl Syscall { /// @brief sys_socket系统调用的实际执行函数 /// @@ -332,6 +336,50 @@ impl Syscall { /// /// @return 成功返回新的文件描述符,失败返回错误码 pub fn accept(fd: usize, addr: *mut SockAddr, addrlen: *mut u32) -> Result { + return Self::do_accept(fd, addr, addrlen, 0); + } + + /// sys_accept4 - accept a connection on a socket + /// + /// + /// If flags is 0, then accept4() is the same as accept(). The + /// following values can be bitwise ORed in flags to obtain different + /// behavior: + /// + /// - SOCK_NONBLOCK + /// Set the O_NONBLOCK file status flag on the open file + /// description (see open(2)) referred to by the new file + /// descriptor. Using this flag saves extra calls to fcntl(2) + /// to achieve the same result. + /// + /// - SOCK_CLOEXEC + /// Set the close-on-exec (FD_CLOEXEC) flag on the new file + /// descriptor. See the description of the O_CLOEXEC flag in + /// open(2) for reasons why this may be useful. + pub fn accept4( + fd: usize, + addr: *mut SockAddr, + addrlen: *mut u32, + mut flags: u32, + ) -> Result { + // 如果flags不合法,返回错误 + if (flags & (!(SOCK_CLOEXEC | SOCK_NONBLOCK)).bits()) != 0 { + return Err(SystemError::EINVAL); + } + + if SOCK_NONBLOCK != FileMode::O_NONBLOCK && ((flags & SOCK_NONBLOCK.bits()) != 0) { + flags = (flags & !SOCK_NONBLOCK.bits()) | FileMode::O_NONBLOCK.bits(); + } + + return Self::do_accept(fd, addr, addrlen, flags); + } + + fn do_accept( + fd: usize, + addr: *mut SockAddr, + addrlen: *mut u32, + flags: u32, + ) -> Result { let socket: Arc = ProcessManager::current_pcb() .get_socket(fd as i32) .ok_or(SystemError::EBADF)?; @@ -344,10 +392,19 @@ impl Syscall { // kdebug!("accept: new_socket={:?}", new_socket); // Insert the new socket into the file descriptor vector let new_socket: Arc = SocketInode::new(new_socket); + + let mut file_mode = FileMode::O_RDWR; + if flags & FileMode::O_NONBLOCK.bits() != 0 { + file_mode |= FileMode::O_NONBLOCK; + } + if flags & FileMode::O_CLOEXEC.bits() != 0 { + file_mode |= FileMode::O_CLOEXEC; + } + let new_fd = ProcessManager::current_pcb() .fd_table() .write() - .alloc_fd(File::new(new_socket, FileMode::O_RDWR)?, None)?; + .alloc_fd(File::new(new_socket, file_mode)?, None)?; // kdebug!("accept: new_fd={}", new_fd); if !addr.is_null() { // kdebug!("accept: write remote_endpoint to user"); diff --git a/kernel/src/syscall/mod.rs b/kernel/src/syscall/mod.rs index 4a392853..29e041b6 100644 --- a/kernel/src/syscall/mod.rs +++ b/kernel/src/syscall/mod.rs @@ -336,25 +336,22 @@ pub const SYS_READ: usize = 0; pub const SYS_WRITE: usize = 1; pub const SYS_OPEN: usize = 2; pub const SYS_CLOSE: usize = 3; -#[allow(dead_code)] pub const SYS_STAT: usize = 4; pub const SYS_FSTAT: usize = 5; -#[allow(dead_code)] pub const SYS_POLL: usize = 7; pub const SYS_LSEEK: usize = 8; pub const SYS_MMAP: usize = 9; pub const SYS_MPROTECT: usize = 10; + pub const SYS_MUNMAP: usize = 11; pub const SYS_BRK: usize = 12; pub const SYS_SIGACTION: usize = 13; -#[allow(dead_code)] pub const SYS_RT_SIGPROCMASK: usize = 14; - pub const SYS_RT_SIGRETURN: usize = 15; + pub const SYS_IOCTL: usize = 16; -#[allow(dead_code)] pub const SYS_WRITEV: usize = 20; pub const SYS_MADVISE: usize = 28; @@ -404,21 +401,18 @@ pub const SYS_MKDIR: usize = 83; pub const SYS_GETTIMEOFDAY: usize = 96; -#[allow(dead_code)] -pub const SYS_SIGALTSTACK: usize = 131; +pub const SYS_GETPPID: usize = 110; +pub const SYS_GETPGID: usize = 121; + +pub const SYS_SIGALTSTACK: usize = 131; +pub const SYS_MKNOD: usize = 133; -#[allow(dead_code)] pub const SYS_ARCH_PRCTL: usize = 158; pub const SYS_REBOOT: usize = 169; -pub const SYS_GETPPID: usize = 110; -pub const SYS_GETPGID: usize = 121; - pub const SYS_GETTID: usize = 186; -pub const SYS_MKNOD: usize = 133; - #[allow(dead_code)] pub const SYS_TKILL: usize = 200; @@ -433,6 +427,8 @@ pub const SYS_EXIT_GROUP: usize = 231; pub const SYS_UNLINK_AT: usize = 263; +pub const SYS_ACCEPT4: usize = 288; + pub const SYS_PIPE: usize = 293; #[allow(dead_code)] @@ -921,6 +917,12 @@ impl Syscall { SYS_LISTEN => Self::listen(args[0], args[1]), SYS_SHUTDOWN => Self::shutdown(args[0], args[1]), SYS_ACCEPT => Self::accept(args[0], args[1] as *mut SockAddr, args[2] as *mut u32), + SYS_ACCEPT4 => Self::accept4( + args[0], + args[1] as *mut SockAddr, + args[2] as *mut u32, + args[3] as u32, + ), SYS_GETSOCKNAME => { Self::getsockname(args[0], args[1] as *mut SockAddr, args[2] as *mut u32) }