mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 08:06:32 +00:00
调整user下libs的libc目录结构 (#103)
* 调整user下libs的libc目录结构 * 修正.gitignore文件的问题 * 修复无法编译的问题 Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
63
user/libs/libc/src/Makefile
Normal file
63
user/libs/libc/src/Makefile
Normal file
@ -0,0 +1,63 @@
|
||||
GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel
|
||||
GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS)))
|
||||
|
||||
all: libc
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
libc_sub_dirs=math sys
|
||||
|
||||
ifeq ($(ARCH), __x86_64__)
|
||||
libc_sub_dirs += sysdeps/x86_64
|
||||
endif
|
||||
|
||||
clean:
|
||||
cargo clean
|
||||
rm -rf $(GARBAGE)
|
||||
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
|
||||
echo "Clean in dir: $$subdir";\
|
||||
cd $$subdir && $(MAKE) clean;\
|
||||
cd .. ;\
|
||||
done
|
||||
|
||||
libc: unistd.o fcntl.o malloc.o errno.o printf.o stdlib.o ctype.o string.o dirent.o time.o libc_rust
|
||||
@list='$(libc_sub_dirs)'; for subdir in $$list; do \
|
||||
echo "make all in $$subdir";\
|
||||
cd $$subdir;\
|
||||
$(MAKE) all CFLAGS="$(CFLAGS) -I $(shell pwd)";\
|
||||
cd ..;\
|
||||
done
|
||||
|
||||
unistd.o: unistd.c
|
||||
$(CC) $(CFLAGS) -c unistd.c -o unistd.o
|
||||
|
||||
fcntl.o: fcntl.c
|
||||
$(CC) $(CFLAGS) -c fcntl.c -o fcntl.o
|
||||
|
||||
malloc.o: malloc.c
|
||||
$(CC) $(CFLAGS) -c malloc.c -o malloc.o
|
||||
|
||||
errno.o: errno.c
|
||||
$(CC) $(CFLAGS) -c errno.c -o errno.o
|
||||
|
||||
printf.o: printf.c
|
||||
$(CC) $(CFLAGS) -c printf.c -o printf.o
|
||||
|
||||
stdlib.o: stdlib.c
|
||||
$(CC) $(CFLAGS) -c stdlib.c -o stdlib.o
|
||||
|
||||
ctype.o: ctype.c
|
||||
$(CC) $(CFLAGS) -c ctype.c -o ctype.o
|
||||
|
||||
string.o: string.c
|
||||
$(CC) $(CFLAGS) -c string.c -o string.o
|
||||
|
||||
dirent.o: dirent.c
|
||||
$(CC) $(CFLAGS) -c dirent.c -o dirent.o
|
||||
|
||||
time.o: time.c
|
||||
$(CC) $(CFLAGS) -c time.c -o time.o
|
||||
|
||||
libc_rust:
|
||||
rustup default nightly
|
||||
cargo +nightly build --release --target ./x86_64-unknown-none.json
|
20
user/libs/libc/src/__libc__.h
Normal file
20
user/libs/libc/src/__libc__.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
# define __BEGIN_HEADER \
|
||||
extern "C" \
|
||||
{
|
||||
|
||||
# define __END_HEADER \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# define __BEGIN_HEADER
|
||||
|
||||
# define __END_HEADER
|
||||
|
||||
#endif
|
75
user/libs/libc/src/ctype.c
Normal file
75
user/libs/libc/src/ctype.c
Normal file
@ -0,0 +1,75 @@
|
||||
#include <libc/src/ctype.h>
|
||||
|
||||
|
||||
int isprint(int c)
|
||||
{
|
||||
if (c >= 0x20 && c <= 0x7e)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int islower(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isupper(int c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isalpha(int c)
|
||||
{
|
||||
if (islower(c) || isupper(c))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isdigit(int c)
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int toupper(int c)
|
||||
{
|
||||
if (c >= 'a' && c <= 'z')
|
||||
{
|
||||
return c - 'a' + 'A';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int tolower(int c)
|
||||
{
|
||||
if (c >= 'A' && c <= 'Z')
|
||||
{
|
||||
return c - 'A' + 'a';
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
int isspace(int c)
|
||||
{
|
||||
return (c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v' || c == ' ');
|
||||
}
|
38
user/libs/libc/src/ctype.h
Normal file
38
user/libs/libc/src/ctype.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <libc/src/__libc__.h>
|
||||
|
||||
|
||||
int isalnum(int c);
|
||||
int isalpha(int c);
|
||||
int isdigit(int c);
|
||||
int islower(int c);
|
||||
int isprint(int c);
|
||||
int isgraph(int c);
|
||||
int iscntrl(int c);
|
||||
int isgraph(int c);
|
||||
int ispunct(int c);
|
||||
int isspace(int c);
|
||||
int isupper(int c);
|
||||
int isxdigit(int c);
|
||||
|
||||
int isascii(int c);
|
||||
|
||||
int tolower(int c);
|
||||
int toupper(int c);
|
||||
|
||||
#define _U 01
|
||||
#define _L 02
|
||||
#define _N 04
|
||||
#define _S 010
|
||||
#define _P 020
|
||||
#define _C 040
|
||||
#define _X 0100
|
||||
#define _B 0200
|
||||
|
||||
extern char _ctype_[256];
|
||||
|
78
user/libs/libc/src/dirent.c
Normal file
78
user/libs/libc/src/dirent.c
Normal file
@ -0,0 +1,78 @@
|
||||
#include "dirent.h"
|
||||
#include "unistd.h"
|
||||
#include "stdio.h"
|
||||
#include "fcntl.h"
|
||||
#include "stddef.h"
|
||||
#include "stdlib.h"
|
||||
#include "string.h"
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
/**
|
||||
* @brief 打开文件夹
|
||||
*
|
||||
* @param dirname
|
||||
* @return DIR*
|
||||
*/
|
||||
struct DIR *opendir(const char *path)
|
||||
{
|
||||
int fd = open(path, O_DIRECTORY);
|
||||
if (fd < 0) // 目录打开失败
|
||||
{
|
||||
printf("Failed to open dir\n");
|
||||
return NULL;
|
||||
}
|
||||
// printf("open dir: %s\n", path);
|
||||
|
||||
// 分配DIR结构体
|
||||
struct DIR *dirp = (struct DIR *)malloc(sizeof(struct DIR));
|
||||
// printf("dirp = %#018lx", dirp);
|
||||
memset(dirp, 0, sizeof(struct DIR));
|
||||
dirp->fd = fd;
|
||||
dirp->buf_len = DIR_BUF_SIZE;
|
||||
dirp->buf_pos = 0;
|
||||
|
||||
return dirp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 关闭文件夹
|
||||
*
|
||||
* @param dirp DIR结构体指针
|
||||
* @return int 成功:0, 失败:-1
|
||||
+--------+--------------------------------+
|
||||
| errno | 描述 |
|
||||
+--------+--------------------------------+
|
||||
| 0 | 成功 |
|
||||
| -EBADF | 当前dirp不指向一个打开了的目录 |
|
||||
| -EINTR | 函数执行期间被信号打断 |
|
||||
+--------+--------------------------------+
|
||||
*/
|
||||
int closedir(struct DIR *dirp)
|
||||
{
|
||||
int retval = close(dirp->fd);
|
||||
free(dirp);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int64_t getdents(int fd, struct dirent *dirent, long count)
|
||||
{
|
||||
return syscall_invoke(SYS_GET_DENTS, fd, (uint64_t)dirent, count, 0, 0, 0, 0, 0);
|
||||
}
|
||||
/**
|
||||
* @brief 从目录中读取数据
|
||||
*
|
||||
* @param dir
|
||||
* @return struct dirent*
|
||||
*/
|
||||
struct dirent *readdir(struct DIR *dir)
|
||||
{
|
||||
// printf("dir->buf = %#018lx\n", (dir->buf));
|
||||
memset((dir->buf), 0, DIR_BUF_SIZE);
|
||||
// printf("memeset_ok\n");
|
||||
int len = getdents(dir->fd, (struct dirent *)dir->buf, DIR_BUF_SIZE);
|
||||
// printf("len=%d\n", len);
|
||||
if (len > 0)
|
||||
return (struct dirent *)dir->buf;
|
||||
else
|
||||
return NULL;
|
||||
}
|
66
user/libs/libc/src/dirent.h
Normal file
66
user/libs/libc/src/dirent.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief inode的属性(copy from vfs.h)
|
||||
*
|
||||
*/
|
||||
#define VFS_IF_FILE (1UL << 0)
|
||||
#define VFS_IF_DIR (1UL << 1)
|
||||
#define VFS_IF_DEVICE (1UL << 2)
|
||||
|
||||
#define DIR_BUF_SIZE 256
|
||||
/**
|
||||
* @brief 文件夹结构体
|
||||
*
|
||||
*/
|
||||
struct DIR
|
||||
{
|
||||
int fd;
|
||||
int buf_pos;
|
||||
int buf_len;
|
||||
char buf[DIR_BUF_SIZE];
|
||||
|
||||
// todo: 加一个指向dirent结构体的指针
|
||||
};
|
||||
|
||||
struct dirent
|
||||
{
|
||||
ino_t d_ino; // 文件序列号
|
||||
off_t d_off; // dir偏移量
|
||||
unsigned short d_reclen; // 目录下的记录数
|
||||
unsigned char d_type; // entry的类型
|
||||
char d_name[]; // 文件entry的名字(是一个零长数组)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 打开文件夹
|
||||
*
|
||||
* @param dirname
|
||||
* @return DIR*
|
||||
*/
|
||||
struct DIR *opendir(const char *dirname);
|
||||
|
||||
/**
|
||||
* @brief 关闭文件夹
|
||||
*
|
||||
* @param dirp DIR结构体指针
|
||||
* @return int 成功:0, 失败:-1
|
||||
+--------+--------------------------------+
|
||||
| errno | 描述 |
|
||||
+--------+--------------------------------+
|
||||
| 0 | 成功 |
|
||||
| -EBADF | 当前dirp不指向一个打开了的目录 |
|
||||
| -EINTR | 函数执行期间被信号打断 |
|
||||
+--------+--------------------------------+
|
||||
*/
|
||||
int closedir(struct DIR *dirp);
|
||||
|
||||
/**
|
||||
* @brief 从目录中读取数据
|
||||
*
|
||||
* @param dir
|
||||
* @return struct dirent*
|
||||
*/
|
||||
struct dirent* readdir(struct DIR* dir);
|
2
user/libs/libc/src/errno.c
Normal file
2
user/libs/libc/src/errno.c
Normal file
@ -0,0 +1,2 @@
|
||||
#include "errno.h"
|
||||
int errno = 0;
|
103
user/libs/libc/src/errno.h
Normal file
103
user/libs/libc/src/errno.h
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
* @file errno.h
|
||||
* @author fslongjin (longjin@RinGoTek.cn)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2022-04-22
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define E2BIG 1 /* 参数列表过长,或者在输出buffer中缺少空间 或者参数比系统内建的最大值要大 Argument list too long. */
|
||||
#define EACCES 2 /* 访问被拒绝 Permission denied */
|
||||
#define EADDRINUSE 3 /* 地址正在被使用 Address in use.*/
|
||||
#define EADDRNOTAVAIL 4 /* 地址不可用 Address not available.*/
|
||||
#define EAFNOSUPPORT 5 /* 地址family不支持 Address family not supported. */
|
||||
#define EAGAIN 6 /* 资源不可用,请重试。 Resource unavailable, try again (may be the same value as [EWOULDBLOCK]).*/
|
||||
#define EALREADY 7 /* 连接已经在处理 Connection already in progress. */
|
||||
#define EBADF 8 /* 错误的文件描述符 Bad file descriptor. */
|
||||
#define EBADMSG 9 /* 错误的消息 Bad message. */
|
||||
|
||||
#define EBUSY 10 /* 设备或资源忙 Device or resource busy. */
|
||||
#define ECANCELED 11 /* 操作被取消 Operation canceled. */
|
||||
#define ECHILD 12 /* 没有子进程 No child processes. */
|
||||
#define ECONNABORTED 13 /* 连接已断开 Connection aborted. */
|
||||
#define ECONNREFUSED 14 /* 连接被拒绝 Connection refused. */
|
||||
#define ECONNRESET 15 /* 连接被重置 Connection reset. */
|
||||
#define EDEADLK 16 /* 资源死锁将要发生 Resource deadlock would occur. */
|
||||
#define EDESTADDRREQ 17 /* 需要目标地址 Destination address required.*/
|
||||
#define EDOM 18 /* 数学参数超出作用域 Mathematics argument out of domain of function. */
|
||||
#define EDQUOT 19 /* 保留使用 Reserved */
|
||||
|
||||
#define EEXIST 20 /* 文件已存在 File exists. */
|
||||
#define EFAULT 21 /* 错误的地址 Bad address */
|
||||
#define EFBIG 22 /* 文件太大 File too large. */
|
||||
#define EHOSTUNREACH 23 /* 主机不可达 Host is unreachable.*/
|
||||
#define EIDRM 24 /* 标志符被移除 Identifier removed. */
|
||||
#define EILSEQ 25 /* 不合法的字符序列 Illegal byte sequence. */
|
||||
#define EINPROGRESS 26 /* 操作正在处理 Operation in progress. */
|
||||
#define EINTR 27 /* 被中断的函数 Interrupted function. */
|
||||
#define EINVAL 28 /* 不可用的参数 Invalid argument. */
|
||||
#define EIO 29 /* I/O错误 I/O error. */
|
||||
|
||||
#define EISCONN 30 /* 套接字已连接 Socket is connected. */
|
||||
#define EISDIR 31 /* 是一个目录 Is a directory */
|
||||
#define ELOOP 32 /* 符号链接级别过多 Too many levels of symbolic links. */
|
||||
#define EMFILE 33 /* 文件描述符的值过大 File descriptor value too large. */
|
||||
#define EMLINK 34 /* 链接数过多 Too many links. */
|
||||
#define EMSGSIZE 35 /* 消息过大 Message too large. */
|
||||
#define EMULTIHOP 36 /* 保留使用 Reserved. */
|
||||
#define ENAMETOOLONG 37 /* 文件名过长 Filename too long. */
|
||||
#define ENETDOWN 38 /* 网络已关闭 Network is down. */
|
||||
#define ENETRESET 39 /* 网络连接已断开 Connection aborted by network. */
|
||||
|
||||
#define ENETUNREACH 40 /* 网络不可达 Network unreachable. */
|
||||
#define ENFILE 41 /* 系统中打开的文件过多 Too many files open in system.*/
|
||||
#define ENOBUFS 42 /* 缓冲区空间不足 No buffer space available. */
|
||||
#define ENODATA 43 /* 队列头没有可读取的消息 No message is available on the STREAM head read queue. */
|
||||
#define ENODEV 44 /* 没有指定的设备 No such device. */
|
||||
#define ENOENT 45 /* 没有指定的文件或目录 No such file or directory. */
|
||||
#define ENOEXEC 46 /* 可执行文件格式错误 Executable file format error. */
|
||||
#define ENOLCK 47 /* 没有可用的锁 No locks available. */
|
||||
#define ENOLINK 48 /* 保留 Reserved. */
|
||||
#define ENOMEM 49 /* 没有足够的空间 Not enough space. */
|
||||
|
||||
#define ENOMSG 50 /* 没有期待类型的消息 No message of the desired type. */
|
||||
#define ENOPROTOOPT 51 /* 协议不可用 Protocol not available. */
|
||||
#define ENOSPC 52 /* 设备上没有空间 No space left on device. */
|
||||
#define ENOSR 53 /* 没有STREAM资源 No STREAM resources.*/
|
||||
#define ENOSTR 54 /* 不是STREAM Not a STREAM */
|
||||
#define ENOSYS 55 /* 功能不支持 Function not supported. */
|
||||
#define ENOTCONN 56 /* 套接字未连接 The socket is not connected. */
|
||||
#define ENOTDIR 57 /* 不是目录 Not a directory. */
|
||||
#define ENOTEMPTY 58 /* 目录非空 Directory not empty. */
|
||||
#define ENOTRECOVERABLE 59 /* 状态不可覆盖 State not recoverable. */
|
||||
|
||||
#define ENOTSOCK 60 /* 不是一个套接字 Not a socket.*/
|
||||
#define ENOTSUP 61 /* 不被支持 Not supported (may be the same value as [EOPNOTSUPP]). */
|
||||
#define ENOTTY 62 /* 不正确的I/O控制操作 Inappropriate I/O control operation. */
|
||||
#define ENXIO 63 /* 没有这样的设备或地址 No such device or address. */
|
||||
#define EOPNOTSUPP 64 /* 套接字不支持该操作 Operation not supported on socket (may be the same value as [ENOTSUP]). */
|
||||
#define EOVERFLOW 65 /* 数值过大,产生溢出 Value too large to be stored in data type. */
|
||||
#define EOWNERDEAD 66 /* 之前的拥有者挂了 Previous owner died. */
|
||||
#define EPERM 67 /* 操作不被允许 Operation not permitted. */
|
||||
#define EPIPE 68 /* 断开的管道 Broken pipe. */
|
||||
#define EPROTO 69 /* 协议错误 Protocol error. */
|
||||
|
||||
#define EPROTONOSUPPORT 70 /* 协议不被支持 Protocol not supported. */
|
||||
#define EPROTOTYPE 71 /* 对于套接字而言,错误的协议 Protocol wrong type for socket. */
|
||||
#define ERANGE 72 /* 结果过大 Result too large. */
|
||||
#define EROFS 73 /* 只读的文件系统 Read-only file system. */
|
||||
#define ESPIPE 74 /* 错误的寻道 Invalid seek. */
|
||||
#define ESRCH 75 /* 没有这样的进程 No such process. */
|
||||
#define ESTALE 76 /* 保留 Reserved. */
|
||||
#define ETIME 77 /* 流式ioctl()超时 Stream ioctl() timeout */
|
||||
#define ETIMEDOUT 78 /* 连接超时 Connection timed out.*/
|
||||
#define ETXTBSY 79 /* 文本文件忙 Text file busy. */
|
||||
|
||||
#define EWOULDBLOCK 80 /* 操作将被禁止 Operation would block (may be the same value as [EAGAIN]). */
|
||||
#define EXDEV 81 /* 跨设备连接 Cross-device link. */
|
||||
|
||||
extern int errno;
|
15
user/libs/libc/src/fcntl.c
Normal file
15
user/libs/libc/src/fcntl.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <libc/src/fcntl.h>
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
/**
|
||||
* @brief 打开文件的接口
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param options 打开选项
|
||||
* @param ...
|
||||
* @return int 文件描述符
|
||||
*/
|
||||
int open(const char *path, int options, ...)
|
||||
{
|
||||
return syscall_invoke(SYS_OPEN, (uint64_t)path, options, 0, 0, 0, 0, 0, 0);
|
||||
}
|
65
user/libs/libc/src/fcntl.h
Normal file
65
user/libs/libc/src/fcntl.h
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* @file fcntl.h
|
||||
* @author fslongjin (longjin@RinGoTek.cn)
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2022-04-26
|
||||
*
|
||||
* @copyright Copyright (c) 2022
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define O_RDONLY 00000000 // Open Read-only
|
||||
#define O_WRONLY 00000001 // Open Write-only
|
||||
#define O_RDWR 00000002 // Open read/write
|
||||
#define O_ACCMODE 00000003 // Mask for file access modes
|
||||
|
||||
#define O_CREAT 00000100 // Create file if it does not exist
|
||||
#define O_EXCL 00000200 // Fail if file already exists
|
||||
#define O_NOCTTY 00000400 // Do not assign controlling terminal
|
||||
|
||||
#define O_TRUNC 00001000 // 文件存在且是普通文件,并以O_RDWR或O_WRONLY打开,则它会被清空
|
||||
|
||||
#define O_APPEND 00002000 // 文件指针会被移动到文件末尾
|
||||
|
||||
#define O_NONBLOCK 00004000 // 非阻塞式IO模式
|
||||
|
||||
#define O_EXEC 00010000 // 以仅执行的方式打开(非目录文件)
|
||||
#define O_SEARCH 00020000 // Open the directory for search only
|
||||
#define O_DIRECTORY 00040000 // 打开的必须是一个目录
|
||||
#define O_NOFOLLOW 00100000 // Do not follow symbolic links
|
||||
|
||||
/*
|
||||
* The constants AT_REMOVEDIR and AT_EACCESS have the same value. AT_EACCESS is
|
||||
* meaningful only to faccessat, while AT_REMOVEDIR is meaningful only to
|
||||
* unlinkat. The two functions do completely different things and therefore,
|
||||
* the flags can be allowed to overlap. For example, passing AT_REMOVEDIR to
|
||||
* faccessat would be undefined behavior and thus treating it equivalent to
|
||||
* AT_EACCESS is valid undefined behavior.
|
||||
*/
|
||||
// 作为当前工作目录的文件描述符(用于指代cwd)
|
||||
#define AT_FDCWD -100
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100 /* Do not follow symbolic links. */
|
||||
#define AT_EACCESS 0x200 /* Test access permitted for effective IDs, not real IDs. */
|
||||
#define AT_REMOVEDIR 0x200 /* Remove directory instead of unlinking file. */
|
||||
#define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */
|
||||
#define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */
|
||||
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
|
||||
|
||||
#define AT_STATX_SYNC_TYPE 0x6000 /* Type of synchronisation required from statx() */
|
||||
#define AT_STATX_SYNC_AS_STAT 0x0000 /* - Do whatever stat() does */
|
||||
#define AT_STATX_FORCE_SYNC 0x2000 /* - Force the attributes to be sync'd with the server */
|
||||
#define AT_STATX_DONT_SYNC 0x4000 /* - Don't sync attributes with the server */
|
||||
|
||||
#define AT_RECURSIVE 0x8000 /* Apply to the entire subtree */
|
||||
|
||||
/**
|
||||
* @brief 打开文件的接口
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param options 打开选项
|
||||
* @param ...
|
||||
* @return int 文件描述符
|
||||
*/
|
||||
int open(const char * path, int options, ...);
|
40
user/libs/libc/src/include/signal.h
Normal file
40
user/libs/libc/src/include/signal.h
Normal file
@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
#define SIGHUP 1
|
||||
#define SIGINT 2
|
||||
#define SIGQUIT 3
|
||||
#define SIGILL 4
|
||||
#define SIGTRAP 5
|
||||
#define SIGABRT 6
|
||||
#define SIGIOT 6
|
||||
#define SIGBUS 7
|
||||
#define SIGFPE 8
|
||||
#define SIGKILL 9
|
||||
#define SIGUSR1 10
|
||||
#define SIGSEGV 11
|
||||
#define SIGUSR2 12
|
||||
#define SIGPIPE 13
|
||||
#define SIGALRM 14
|
||||
#define SIGTERM 15
|
||||
#define SIGSTKFLT 16
|
||||
#define SIGCHLD 17
|
||||
#define SIGCONT 18
|
||||
#define SIGSTOP 19
|
||||
#define SIGTSTP 20
|
||||
#define SIGTTIN 21
|
||||
#define SIGTTOU 22
|
||||
#define SIGURG 23
|
||||
#define SIGXCPU 24
|
||||
#define SIGXFSZ 25
|
||||
#define SIGVTALRM 26
|
||||
#define SIGPROF 27
|
||||
#define SIGWINCH 28
|
||||
#define SIGIO 29
|
||||
#define SIGPOLL SIGIO
|
||||
|
||||
#define SIGPWR 30
|
||||
#define SIGSYS 31
|
||||
|
||||
/* These should not be considered constants from userland. */
|
||||
#define SIGRTMIN 32
|
||||
#define SIGRTMAX MAX_SIG_NUM
|
21
user/libs/libc/src/lib.rs
Normal file
21
user/libs/libc/src/lib.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#![no_std] // <1>
|
||||
#![no_main] // <1>
|
||||
#![feature(core_intrinsics)] // <2>
|
||||
#![feature(alloc_error_handler)]
|
||||
#![feature(panic_info_message)]
|
||||
|
||||
#[allow(non_upper_case_globals)]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(non_snake_case)]
|
||||
|
||||
|
||||
use core::panic::PanicInfo;
|
||||
#[panic_handler]
|
||||
fn panic(_info: &PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn scanf() {
|
||||
|
||||
}
|
392
user/libs/libc/src/malloc.c
Normal file
392
user/libs/libc/src/malloc.c
Normal file
@ -0,0 +1,392 @@
|
||||
#include <libc/src/stdlib.h>
|
||||
#include <libsystem/syscall.h>
|
||||
#include <libc/src/stddef.h>
|
||||
#include <libc/src/unistd.h>
|
||||
#include <libc/src/errno.h>
|
||||
#include <libc/src/stdio.h>
|
||||
|
||||
#define PAGE_4K_SHIFT 12
|
||||
#define PAGE_2M_SHIFT 21
|
||||
#define PAGE_1G_SHIFT 30
|
||||
#define PAGE_GDT_SHIFT 39
|
||||
|
||||
// 不同大小的页的容量
|
||||
#define PAGE_4K_SIZE (1UL << PAGE_4K_SHIFT)
|
||||
#define PAGE_2M_SIZE (1UL << PAGE_2M_SHIFT)
|
||||
#define PAGE_1G_SIZE (1UL << PAGE_1G_SHIFT)
|
||||
|
||||
// 屏蔽低于x的数值
|
||||
#define PAGE_4K_MASK (~(PAGE_4K_SIZE - 1))
|
||||
#define PAGE_2M_MASK (~(PAGE_2M_SIZE - 1))
|
||||
|
||||
// 将addr按照x的上边界对齐
|
||||
#define PAGE_4K_ALIGN(addr) (((unsigned long)(addr) + PAGE_4K_SIZE - 1) & PAGE_4K_MASK)
|
||||
#define PAGE_2M_ALIGN(addr) (((unsigned long)(addr) + PAGE_2M_SIZE - 1) & PAGE_2M_MASK)
|
||||
|
||||
/**
|
||||
* @brief 显式链表的结点
|
||||
*
|
||||
*/
|
||||
typedef struct malloc_mem_chunk_t
|
||||
{
|
||||
uint64_t length; // 整个块所占用的内存区域的大小
|
||||
struct malloc_mem_chunk_t *prev; // 上一个结点的指针
|
||||
struct malloc_mem_chunk_t *next; // 下一个结点的指针
|
||||
} malloc_mem_chunk_t;
|
||||
|
||||
static uint64_t brk_base_addr = 0; // 堆区域的内存基地址
|
||||
static uint64_t brk_max_addr = 0; // 堆区域的内存最大地址
|
||||
static uint64_t brk_managed_addr = 0; // 堆区域已经被管理的地址
|
||||
|
||||
// 空闲链表
|
||||
// 按start_addr升序排序
|
||||
static malloc_mem_chunk_t *malloc_free_list = NULL;
|
||||
static malloc_mem_chunk_t *malloc_free_list_end = NULL; // 空闲链表的末尾结点
|
||||
|
||||
static uint64_t count_last_free_size = 0; // 统计距离上一次回收内存,已经free了多少内存
|
||||
|
||||
/**
|
||||
* @brief 将块插入空闲链表
|
||||
*
|
||||
* @param ck 待插入的块
|
||||
*/
|
||||
static void malloc_insert_free_list(malloc_mem_chunk_t *ck);
|
||||
|
||||
/**
|
||||
* @brief 当堆顶空闲空间大于2个页的空间的时候,释放1个页
|
||||
*
|
||||
*/
|
||||
static void release_brk();
|
||||
|
||||
/**
|
||||
* @brief 在链表中检索符合要求的空闲块(best fit)
|
||||
*
|
||||
* @param size 块的大小
|
||||
* @return malloc_mem_chunk_t*
|
||||
*/
|
||||
static malloc_mem_chunk_t *malloc_query_free_chunk_bf(uint64_t size)
|
||||
{
|
||||
// 在满足best fit的前提下,尽可能的使分配的内存在低地址
|
||||
// 使得总的堆内存可以更快被释放
|
||||
|
||||
if (malloc_free_list == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
malloc_mem_chunk_t *ptr = malloc_free_list;
|
||||
malloc_mem_chunk_t *best = NULL;
|
||||
// printf("query size=%d", size);
|
||||
while (ptr != NULL)
|
||||
{
|
||||
// printf("ptr->length=%#010lx\n", ptr->length);
|
||||
if (ptr->length == size)
|
||||
{
|
||||
best = ptr;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ptr->length > size)
|
||||
{
|
||||
if (best == NULL)
|
||||
best = ptr;
|
||||
else if (best->length > ptr->length)
|
||||
best = ptr;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在链表中检索符合要求的空闲块(first fit)
|
||||
*
|
||||
* @param size
|
||||
* @return malloc_mem_chunk_t*
|
||||
*/
|
||||
static malloc_mem_chunk_t *malloc_query_free_chunk_ff(uint64_t size)
|
||||
{
|
||||
if (malloc_free_list == NULL)
|
||||
return NULL;
|
||||
malloc_mem_chunk_t *ptr = malloc_free_list;
|
||||
|
||||
while (ptr)
|
||||
{
|
||||
if (ptr->length >= size)
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 扩容malloc管理的内存区域
|
||||
*
|
||||
* @param size 扩大的内存大小
|
||||
*/
|
||||
static int malloc_enlarge(int64_t size)
|
||||
{
|
||||
if (brk_base_addr == 0) // 第一次调用,需要初始化
|
||||
{
|
||||
brk_base_addr = brk(-1);
|
||||
// printf("brk_base_addr=%#018lx\n", brk_base_addr);
|
||||
brk_managed_addr = brk_base_addr;
|
||||
brk_max_addr = brk(-2);
|
||||
}
|
||||
|
||||
int64_t free_space = brk_max_addr - brk_managed_addr;
|
||||
// printf("size=%ld\tfree_space=%ld\n", size, free_space);
|
||||
if (free_space < size) // 现有堆空间不足
|
||||
{
|
||||
if (sbrk(size - free_space) != (void *)(-1))
|
||||
brk_max_addr = brk((-2));
|
||||
else
|
||||
{
|
||||
put_string("malloc_enlarge(): no_mem\n", COLOR_YELLOW, COLOR_BLACK);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
// printf("brk max addr = %#018lx\n", brk_max_addr);
|
||||
}
|
||||
|
||||
// 扩展管理的堆空间
|
||||
// 在新分配的内存的底部放置header
|
||||
// printf("managed addr = %#018lx\n", brk_managed_addr);
|
||||
malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)brk_managed_addr;
|
||||
new_ck->length = brk_max_addr - brk_managed_addr;
|
||||
// printf("new_ck->start_addr=%#018lx\tbrk_max_addr=%#018lx\tbrk_managed_addr=%#018lx\n", (uint64_t)new_ck, brk_max_addr, brk_managed_addr);
|
||||
new_ck->prev = NULL;
|
||||
new_ck->next = NULL;
|
||||
brk_managed_addr = brk_max_addr;
|
||||
|
||||
malloc_insert_free_list(new_ck);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 合并空闲块
|
||||
*
|
||||
*/
|
||||
static void malloc_merge_free_chunk()
|
||||
{
|
||||
if (malloc_free_list == NULL)
|
||||
return;
|
||||
malloc_mem_chunk_t *ptr = malloc_free_list->next;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
// 内存块连续
|
||||
if (((uint64_t)(ptr->prev) + ptr->prev->length == (uint64_t)ptr))
|
||||
{
|
||||
// printf("merged %#018lx and %#018lx\n", (uint64_t)ptr, (uint64_t)(ptr->prev));
|
||||
// 将ptr与前面的空闲块合并
|
||||
ptr->prev->length += ptr->length;
|
||||
ptr->prev->next = ptr->next;
|
||||
if (ptr->next == NULL)
|
||||
malloc_free_list_end = ptr->prev;
|
||||
else
|
||||
ptr->next->prev = ptr->prev;
|
||||
// 由于内存组成结构的原因,不需要free掉header
|
||||
ptr = ptr->prev;
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将块插入空闲链表
|
||||
*
|
||||
* @param ck 待插入的块
|
||||
*/
|
||||
static void malloc_insert_free_list(malloc_mem_chunk_t *ck)
|
||||
{
|
||||
if (malloc_free_list == NULL) // 空闲链表为空
|
||||
{
|
||||
malloc_free_list = ck;
|
||||
malloc_free_list_end = ck;
|
||||
ck->prev = ck->next = NULL;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
malloc_mem_chunk_t *ptr = malloc_free_list;
|
||||
while (ptr != NULL)
|
||||
{
|
||||
if ((uint64_t)ptr < (uint64_t)ck)
|
||||
{
|
||||
if (ptr->next == NULL) // 当前是最后一个项
|
||||
{
|
||||
ptr->next = ck;
|
||||
ck->next = NULL;
|
||||
ck->prev = ptr;
|
||||
malloc_free_list_end = ck;
|
||||
break;
|
||||
}
|
||||
else if ((uint64_t)(ptr->next) > (uint64_t)ck)
|
||||
{
|
||||
ck->prev = ptr;
|
||||
ck->next = ptr->next;
|
||||
ptr->next = ck;
|
||||
ck->next->prev = ck;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // 在ptr之前插入
|
||||
{
|
||||
|
||||
if (ptr->prev == NULL) // 是第一个项
|
||||
{
|
||||
malloc_free_list = ck;
|
||||
ck->prev = NULL;
|
||||
ck->next = ptr;
|
||||
ptr->prev = ck;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ck->prev = ptr->prev;
|
||||
ck->next = ptr;
|
||||
ck->prev->next = ck;
|
||||
ptr->prev = ck;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ptr = ptr->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取一块堆内存
|
||||
*
|
||||
* @param size 内存大小
|
||||
* @return void* 内存空间的指针
|
||||
*
|
||||
* 分配内存的时候,结点的prev next指针所占用的空间被当做空闲空间分配出去
|
||||
*/
|
||||
void *malloc(ssize_t size)
|
||||
{
|
||||
// printf("malloc\n");
|
||||
// 计算需要分配的块的大小
|
||||
if (size + sizeof(uint64_t) <= sizeof(malloc_mem_chunk_t))
|
||||
size = sizeof(malloc_mem_chunk_t);
|
||||
else
|
||||
size += sizeof(uint64_t);
|
||||
|
||||
// 采用best fit
|
||||
malloc_mem_chunk_t *ck = malloc_query_free_chunk_bf(size);
|
||||
|
||||
if (ck == NULL) // 没有空闲块
|
||||
{
|
||||
|
||||
// printf("no free blocks\n");
|
||||
// 尝试合并空闲块
|
||||
malloc_merge_free_chunk();
|
||||
ck = malloc_query_free_chunk_bf(size);
|
||||
|
||||
// 找到了合适的块
|
||||
if (ck)
|
||||
goto found;
|
||||
|
||||
// printf("before enlarge\n");
|
||||
// 找不到合适的块,扩容堆区域
|
||||
if (malloc_enlarge(size) == -ENOMEM)
|
||||
return (void *)-ENOMEM; // 内存不足
|
||||
|
||||
|
||||
malloc_merge_free_chunk(); // 扩容后运行合并,否则会导致碎片
|
||||
|
||||
// 扩容后再次尝试获取
|
||||
|
||||
ck = malloc_query_free_chunk_bf(size);
|
||||
}
|
||||
found:;
|
||||
|
||||
// printf("ck = %#018lx\n", (uint64_t)ck);
|
||||
if (ck == NULL)
|
||||
return (void *)-ENOMEM;
|
||||
// printf("ck->prev=%#018lx ck->next=%#018lx\n", ck->prev, ck->next);
|
||||
// 分配空闲块
|
||||
// 从空闲链表取出
|
||||
if (ck->prev == NULL) // 当前是链表的第一个块
|
||||
{
|
||||
malloc_free_list = ck->next;
|
||||
}
|
||||
else
|
||||
ck->prev->next = ck->next;
|
||||
|
||||
if (ck->next != NULL) // 当前不是最后一个块
|
||||
ck->next->prev = ck->prev;
|
||||
else
|
||||
malloc_free_list_end = ck->prev;
|
||||
|
||||
// 当前块剩余的空间还能容纳多一个结点的空间,则分裂当前块
|
||||
if ((int64_t)(ck->length) - size > sizeof(malloc_mem_chunk_t))
|
||||
{
|
||||
// printf("seperate\n");
|
||||
malloc_mem_chunk_t *new_ck = (malloc_mem_chunk_t *)(((uint64_t)ck) + size);
|
||||
new_ck->length = ck->length - size;
|
||||
new_ck->prev = new_ck->next = NULL;
|
||||
// printf("new_ck=%#018lx, new_ck->length=%#010lx\n", (uint64_t)new_ck, new_ck->length);
|
||||
ck->length = size;
|
||||
malloc_insert_free_list(new_ck);
|
||||
}
|
||||
// printf("malloc done: %#018lx, length=%#018lx\n", ((uint64_t)ck + sizeof(uint64_t)), ck->length);
|
||||
// 此时链表结点的指针的空间被分配出去
|
||||
return (void *)((uint64_t)ck + sizeof(uint64_t));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 当堆顶空闲空间大于2个页的空间的时候,释放1个页
|
||||
*
|
||||
*/
|
||||
static void release_brk()
|
||||
{
|
||||
// 先检测最顶上的块
|
||||
// 由于块按照开始地址排列,因此找最后一个块
|
||||
if (malloc_free_list_end == NULL)
|
||||
{
|
||||
printf("release(): free list end is null. \n");
|
||||
return;
|
||||
}
|
||||
if ((uint64_t)malloc_free_list_end + malloc_free_list_end->length == brk_max_addr && (uint64_t)malloc_free_list_end <= brk_max_addr - (PAGE_2M_SIZE << 1))
|
||||
{
|
||||
int64_t delta = ((brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK) - PAGE_2M_SIZE;
|
||||
// printf("(brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK=%#018lx\n ", (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK);
|
||||
// printf("PAGE_2M_SIZE=%#018lx\n", PAGE_2M_SIZE);
|
||||
// printf("tdfghgbdfggkmfn=%#018lx\n ", (brk_max_addr - (uint64_t)malloc_free_list_end) & PAGE_2M_MASK - PAGE_2M_SIZE);
|
||||
// printf("delta=%#018lx\n ", delta);
|
||||
if (delta <= 0) // 不用释放内存
|
||||
return;
|
||||
sbrk(-delta);
|
||||
brk_max_addr = brk(-2);
|
||||
brk_managed_addr = brk_max_addr;
|
||||
|
||||
malloc_free_list_end->length = brk_max_addr - (uint64_t)malloc_free_list_end;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @brief 释放一块堆内存
|
||||
*
|
||||
* @param ptr 堆内存的指针
|
||||
*/
|
||||
void free(void *ptr)
|
||||
{
|
||||
// 找到结点(此时prev和next都处于未初始化的状态)
|
||||
malloc_mem_chunk_t *ck = (malloc_mem_chunk_t *)((uint64_t)ptr - sizeof(uint64_t));
|
||||
// printf("free(): addr = %#018lx\t len=%#018lx\n", (uint64_t)ck, ck->length);
|
||||
count_last_free_size += ck->length;
|
||||
|
||||
malloc_insert_free_list(ck);
|
||||
|
||||
if (count_last_free_size > PAGE_2M_SIZE)
|
||||
{
|
||||
count_last_free_size = 0;
|
||||
malloc_merge_free_chunk();
|
||||
release_brk();
|
||||
}
|
||||
}
|
12
user/libs/libc/src/math.h
Normal file
12
user/libs/libc/src/math.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "stddef.h"
|
||||
|
||||
double fabs(double x);
|
||||
float fabsf(float x);
|
||||
long double fabsl(long double x);
|
||||
|
||||
double round(double x);
|
||||
float roundf(float x);
|
||||
long double roundl(long double x);
|
||||
|
||||
int64_t pow(int64_t x, int y);
|
14
user/libs/libc/src/math/Makefile
Normal file
14
user/libs/libc/src/math/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
all: fabs.o round.o pow.o
|
||||
|
||||
fabs.o: fabs.c
|
||||
$(CC) $(CFLAGS) -c fabs.c -o fabs.o
|
||||
|
||||
round.o: round.c
|
||||
$(CC) $(CFLAGS) -c round.c -o round.o
|
||||
|
||||
pow.o: pow.c
|
||||
$(CC) $(CFLAGS) -c pow.c -o pow.o
|
29
user/libs/libc/src/math/fabs.c
Normal file
29
user/libs/libc/src/math/fabs.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include <libc/src/math.h>
|
||||
#include <libc/src/sys/types.h>
|
||||
#include "libm.h"
|
||||
double fabs(double x)
|
||||
{
|
||||
union
|
||||
{
|
||||
double f;
|
||||
uint64_t i;
|
||||
} u = {x};
|
||||
u.i &= -1ULL / 2;
|
||||
return u.f;
|
||||
}
|
||||
|
||||
|
||||
#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024
|
||||
long double fabsl(long double x)
|
||||
{
|
||||
return fabs(x);
|
||||
}
|
||||
#elif (__LDBL_MANT_DIG__ == 64 || __LDBL_MANT_DIG__ == 113) && __LDBL_MAX_EXP__ == 16384
|
||||
long double fabsl(long double x)
|
||||
{
|
||||
union ldshape u = {x};
|
||||
|
||||
u.i.se &= 0x7fff;
|
||||
return u.f;
|
||||
}
|
||||
#endif
|
75
user/libs/libc/src/math/libm.h
Normal file
75
user/libs/libc/src/math/libm.h
Normal file
@ -0,0 +1,75 @@
|
||||
#pragma once
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
// ===== 描述long double 的数据比特结构
|
||||
#if __LDBL_MANT_DIG__ == 53 && __LDBL_MAX_EXP__ == 1024
|
||||
#elif __LDBL_MANT_DIG__ == 64 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
union ldshape
|
||||
{
|
||||
long double f;
|
||||
struct
|
||||
{
|
||||
uint64_t m;
|
||||
uint16_t se;
|
||||
} i;
|
||||
};
|
||||
#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
union ldshape
|
||||
{
|
||||
long double f;
|
||||
struct
|
||||
{
|
||||
uint64_t lo;
|
||||
uint32_t mid;
|
||||
uint16_t top;
|
||||
uint16_t se;
|
||||
} i;
|
||||
struct
|
||||
{
|
||||
uint64_t lo;
|
||||
uint64_t hi;
|
||||
} i2;
|
||||
};
|
||||
#elif __LDBL_MANT_DIG__ == 113 && __LDBL_MAX_EXP__ == 16384 && __BYTE_ORDER__ == __BIG_ENDIAN
|
||||
union ldshape
|
||||
{
|
||||
long double f;
|
||||
struct
|
||||
{
|
||||
uint16_t se;
|
||||
uint16_t top;
|
||||
uint32_t mid;
|
||||
uint64_t lo;
|
||||
} i;
|
||||
struct
|
||||
{
|
||||
uint64_t hi;
|
||||
uint64_t lo;
|
||||
} i2;
|
||||
};
|
||||
#else
|
||||
#error Unsupported long double representation
|
||||
#endif
|
||||
|
||||
#define FORCE_EVAL(x) \
|
||||
do \
|
||||
{ \
|
||||
if (sizeof(x) == sizeof(float)) \
|
||||
{ \
|
||||
volatile float __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} \
|
||||
else if (sizeof(x) == sizeof(double)) \
|
||||
{ \
|
||||
volatile double __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
volatile long double __x; \
|
||||
__x = (x); \
|
||||
(void)__x; \
|
||||
} \
|
||||
} while (0)
|
10
user/libs/libc/src/math/pow.c
Normal file
10
user/libs/libc/src/math/pow.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include <libc/src/math.h>
|
||||
#include <libc/src/stddef.h>
|
||||
|
||||
int64_t pow(int64_t x, int y)
|
||||
{
|
||||
int64_t res = 1;
|
||||
for (int i = 0; i < y; ++i)
|
||||
res *= x;
|
||||
return res;
|
||||
}
|
41
user/libs/libc/src/math/round.c
Normal file
41
user/libs/libc/src/math/round.c
Normal file
@ -0,0 +1,41 @@
|
||||
#include "libm.h"
|
||||
|
||||
#if __FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1
|
||||
#define EPS __DBL_EPSILON__
|
||||
#elif __FLT_EVAL_METHOD__ == 2
|
||||
#define EPS __LDBL_EPSILON__
|
||||
#endif
|
||||
static const double toint = 1 / EPS;
|
||||
|
||||
double round(double x)
|
||||
{
|
||||
union
|
||||
{
|
||||
double f;
|
||||
uint64_t i;
|
||||
} u = {x};
|
||||
|
||||
int e = u.i >> 52 & 0x7ff;
|
||||
double y;
|
||||
|
||||
if (e >= 0x3ff + 52)
|
||||
return x;
|
||||
if (u.i >> 63)
|
||||
x = -x;
|
||||
if (e < 0x3ff - 1)
|
||||
{
|
||||
/* raise inexact if x!=0 */
|
||||
FORCE_EVAL(x + toint);
|
||||
return 0 * u.f;
|
||||
}
|
||||
y = x + toint - toint - x;
|
||||
if (y > 0.5)
|
||||
y = y + x - 1;
|
||||
else if (y <= -0.5)
|
||||
y = y + x + 1;
|
||||
else
|
||||
y = y + x;
|
||||
if (u.i >> 63)
|
||||
y = -y;
|
||||
return y;
|
||||
}
|
554
user/libs/libc/src/printf.c
Normal file
554
user/libs/libc/src/printf.c
Normal file
@ -0,0 +1,554 @@
|
||||
#include "printf.h"
|
||||
|
||||
#include <libc/src/math.h>
|
||||
#include <libc/src/stdio.h>
|
||||
#include <libc/src/stdlib.h>
|
||||
#include <libc/src/string.h>
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags);
|
||||
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags);
|
||||
|
||||
static int skip_and_atoi(const char **s)
|
||||
{
|
||||
/**
|
||||
* @brief 获取连续的一段字符对应整数的值
|
||||
* @param:**s 指向 指向字符串的指针 的指针
|
||||
*/
|
||||
int ans = 0;
|
||||
while (is_digit(**s))
|
||||
{
|
||||
ans = ans * 10 + (**s) - '0';
|
||||
++(*s);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 往屏幕上输出字符串
|
||||
*
|
||||
* @param str 字符串指针
|
||||
* @param front_color 前景色
|
||||
* @param bg_color 背景色
|
||||
* @return int64_t
|
||||
*/
|
||||
int64_t put_string(char *str, uint64_t front_color, uint64_t bg_color)
|
||||
{
|
||||
return syscall_invoke(SYS_PUT_STRING, (uint64_t)str, front_color, bg_color, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int printf(const char *fmt, ...)
|
||||
{
|
||||
char buf[4096];
|
||||
int count = 0;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
count = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
put_string(buf, COLOR_WHITE, COLOR_BLACK);
|
||||
return count;
|
||||
}
|
||||
|
||||
int sprintf(char *buf, const char *fmt, ...)
|
||||
{
|
||||
int count = 0;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
count = vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中
|
||||
* @param buf 结果缓冲区
|
||||
* @param fmt 格式化字符串
|
||||
* @param args 内容
|
||||
* @return 最终字符串的长度
|
||||
*/
|
||||
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||
{
|
||||
// 当需要输出的字符串的指针为空时,使用该字符填充目标字符串的指针
|
||||
static const char __end_zero_char = '\0';
|
||||
|
||||
char *str = NULL, *s = NULL;
|
||||
|
||||
str = buf;
|
||||
|
||||
int flags; // 用来存储格式信息的bitmap
|
||||
int field_width; //区域宽度
|
||||
int precision; //精度
|
||||
int qualifier; //数据显示的类型
|
||||
int len;
|
||||
|
||||
//开始解析字符串
|
||||
for (; *fmt; ++fmt)
|
||||
{
|
||||
//内容不涉及到格式化,直接输出
|
||||
if (*fmt != '%')
|
||||
{
|
||||
*str = *fmt;
|
||||
++str;
|
||||
continue;
|
||||
}
|
||||
|
||||
//开始格式化字符串
|
||||
|
||||
//清空标志位和field宽度
|
||||
field_width = flags = 0;
|
||||
|
||||
bool flag_tmp = true;
|
||||
bool flag_break = false;
|
||||
|
||||
++fmt;
|
||||
while (flag_tmp)
|
||||
{
|
||||
switch (*fmt)
|
||||
{
|
||||
case '\0':
|
||||
//结束解析
|
||||
flag_break = true;
|
||||
flag_tmp = false;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
// 左对齐
|
||||
flags |= LEFT;
|
||||
++fmt;
|
||||
break;
|
||||
case '+':
|
||||
//在正数前面显示加号
|
||||
flags |= PLUS;
|
||||
++fmt;
|
||||
break;
|
||||
case ' ':
|
||||
flags |= SPACE;
|
||||
++fmt;
|
||||
break;
|
||||
case '#':
|
||||
//在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
|
||||
flags |= SPECIAL;
|
||||
++fmt;
|
||||
break;
|
||||
case '0':
|
||||
//显示的数字之前填充‘0’来取代空格
|
||||
flags |= PAD_ZERO;
|
||||
++fmt;
|
||||
break;
|
||||
default:
|
||||
flag_tmp = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag_break)
|
||||
break;
|
||||
|
||||
//获取区域宽度
|
||||
field_width = -1;
|
||||
if (*fmt == '*')
|
||||
{
|
||||
field_width = va_arg(args, int);
|
||||
++fmt;
|
||||
}
|
||||
else if (is_digit(*fmt))
|
||||
{
|
||||
field_width = skip_and_atoi(&fmt);
|
||||
if (field_width < 0)
|
||||
{
|
||||
field_width = -field_width;
|
||||
flags |= LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
//获取小数精度
|
||||
precision = -1;
|
||||
if (*fmt == '.')
|
||||
{
|
||||
++fmt;
|
||||
if (*fmt == '*')
|
||||
{
|
||||
precision = va_arg(args, int);
|
||||
++fmt;
|
||||
}
|
||||
else if is_digit (*fmt)
|
||||
{
|
||||
precision = skip_and_atoi(&fmt);
|
||||
}
|
||||
}
|
||||
|
||||
//获取要显示的数据的类型
|
||||
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
|
||||
{
|
||||
qualifier = *fmt;
|
||||
++fmt;
|
||||
}
|
||||
//为了支持lld
|
||||
if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd')
|
||||
++fmt;
|
||||
|
||||
//转化成字符串
|
||||
long long *ip;
|
||||
switch (*fmt)
|
||||
{
|
||||
//输出 %
|
||||
case '%':
|
||||
*str++ = '%';
|
||||
|
||||
break;
|
||||
// 显示一个字符
|
||||
case 'c':
|
||||
//靠右对齐
|
||||
if (!(flags & LEFT))
|
||||
{
|
||||
while (--field_width > 0)
|
||||
{
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
}
|
||||
|
||||
*str++ = (unsigned char)va_arg(args, int);
|
||||
|
||||
while (--field_width > 0)
|
||||
{
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
//显示一个字符串
|
||||
case 's':
|
||||
s = va_arg(args, char *);
|
||||
if (!s)
|
||||
s = &__end_zero_char;
|
||||
len = strlen(s);
|
||||
if (precision < 0)
|
||||
{
|
||||
//未指定精度
|
||||
precision = len;
|
||||
}
|
||||
|
||||
else if (len > precision)
|
||||
{
|
||||
len = precision;
|
||||
}
|
||||
|
||||
//靠右对齐
|
||||
if (!(flags & LEFT))
|
||||
while (len < field_width--)
|
||||
{
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
*str = *s;
|
||||
++s;
|
||||
++str;
|
||||
}
|
||||
|
||||
while (len < field_width--)
|
||||
{
|
||||
*str = ' ';
|
||||
++str;
|
||||
}
|
||||
|
||||
break;
|
||||
//以八进制显示字符串
|
||||
case 'o':
|
||||
flags |= SMALL;
|
||||
case 'O':
|
||||
flags |= SPECIAL;
|
||||
if (qualifier == 'l')
|
||||
str = write_num(str, va_arg(args, long long), 8, field_width, precision, flags);
|
||||
else
|
||||
str = write_num(str, va_arg(args, int), 8, field_width, precision, flags);
|
||||
break;
|
||||
|
||||
//打印指针指向的地址
|
||||
case 'p':
|
||||
if (field_width == 0)
|
||||
{
|
||||
field_width = 2 * sizeof(void *);
|
||||
flags |= PAD_ZERO;
|
||||
}
|
||||
|
||||
str = write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags);
|
||||
|
||||
break;
|
||||
|
||||
//打印十六进制
|
||||
case 'x':
|
||||
flags |= SMALL;
|
||||
case 'X':
|
||||
// flags |= SPECIAL;
|
||||
if (qualifier == 'l')
|
||||
str = write_num(str, va_arg(args, int64_t), 16, field_width, precision, flags);
|
||||
else
|
||||
str = write_num(str, va_arg(args, int), 16, field_width, precision, flags);
|
||||
break;
|
||||
|
||||
//打印十进制有符号整数
|
||||
case 'i':
|
||||
case 'd':
|
||||
|
||||
flags |= SIGN;
|
||||
if (qualifier == 'l')
|
||||
str = write_num(str, va_arg(args, long long), 10, field_width, precision, flags);
|
||||
else
|
||||
str = write_num(str, va_arg(args, int), 10, field_width, precision, flags);
|
||||
break;
|
||||
|
||||
//打印十进制无符号整数
|
||||
case 'u':
|
||||
if (qualifier == 'l')
|
||||
str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags);
|
||||
else
|
||||
str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags);
|
||||
break;
|
||||
|
||||
//输出有效字符数量到*ip对应的变量
|
||||
case 'n':
|
||||
|
||||
if (qualifier == 'l')
|
||||
ip = va_arg(args, long long *);
|
||||
else
|
||||
ip = (int64_t *)va_arg(args, int *);
|
||||
|
||||
*ip = str - buf;
|
||||
break;
|
||||
case 'f':
|
||||
// 默认精度为3
|
||||
if (precision < 0)
|
||||
precision = 3;
|
||||
|
||||
str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags);
|
||||
|
||||
break;
|
||||
|
||||
//对于不识别的控制符,直接输出
|
||||
default:
|
||||
*str++ = '%';
|
||||
if (*fmt)
|
||||
*str++ = *fmt;
|
||||
else
|
||||
--fmt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*str = '\0';
|
||||
|
||||
//返回缓冲区已有字符串的长度。
|
||||
return str - buf;
|
||||
}
|
||||
|
||||
static char *write_num(char *str, uint64_t num, int base, int field_width, int precision, int flags)
|
||||
{
|
||||
/**
|
||||
* @brief 将数字按照指定的要求转换成对应的字符串
|
||||
*
|
||||
* @param str 要返回的字符串
|
||||
* @param num 要打印的数值
|
||||
* @param base 基数
|
||||
* @param field_width 区域宽度
|
||||
* @param precision 精度
|
||||
* @param flags 标志位
|
||||
*/
|
||||
|
||||
// 首先判断是否支持该进制
|
||||
if (base < 2 || base > 36)
|
||||
return 0;
|
||||
char pad, sign, tmp_num[100];
|
||||
|
||||
const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
// 显示小写字母
|
||||
if (flags & SMALL)
|
||||
digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
if (flags & LEFT)
|
||||
flags &= ~PAD_ZERO;
|
||||
// 设置填充元素
|
||||
pad = (flags & PAD_ZERO) ? '0' : ' ';
|
||||
|
||||
sign = 0;
|
||||
|
||||
if (flags & SIGN)
|
||||
{
|
||||
int64_t signed_num = (int64_t)num;
|
||||
if (signed_num < 0)
|
||||
{
|
||||
sign = '-';
|
||||
num = -signed_num;
|
||||
}
|
||||
else
|
||||
num = signed_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置符号
|
||||
sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
|
||||
}
|
||||
|
||||
// sign占用了一个宽度
|
||||
if (sign)
|
||||
--field_width;
|
||||
|
||||
if (flags & SPECIAL)
|
||||
if (base == 16) // 0x占用2个位置
|
||||
field_width -= 2;
|
||||
else if (base == 8) // O占用一个位置
|
||||
--field_width;
|
||||
|
||||
int js_num = 0; // 临时数字字符串tmp_num的长度
|
||||
|
||||
if (num == 0)
|
||||
tmp_num[js_num++] = '0';
|
||||
else
|
||||
{
|
||||
num = llabs(num);
|
||||
//进制转换
|
||||
while (num > 0)
|
||||
{
|
||||
tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位
|
||||
num /= base;
|
||||
}
|
||||
}
|
||||
|
||||
if (js_num > precision)
|
||||
precision = js_num;
|
||||
|
||||
field_width -= precision;
|
||||
|
||||
// 靠右对齐
|
||||
if (!(flags & (LEFT + PAD_ZERO)))
|
||||
while (field_width-- > 0)
|
||||
*str++ = ' ';
|
||||
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
if (flags & SPECIAL)
|
||||
if (base == 16)
|
||||
{
|
||||
*str++ = '0';
|
||||
*str++ = digits[33];
|
||||
}
|
||||
else if (base == 8)
|
||||
*str++ = digits[24]; //注意这里是英文字母O或者o
|
||||
if (!(flags & LEFT))
|
||||
while (field_width-- > 0)
|
||||
*str++ = pad;
|
||||
while (js_num < precision)
|
||||
{
|
||||
--precision;
|
||||
*str++ = '0';
|
||||
}
|
||||
|
||||
while (js_num-- > 0)
|
||||
*str++ = tmp_num[js_num];
|
||||
|
||||
while (field_width-- > 0)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags)
|
||||
{
|
||||
/**
|
||||
* @brief 将浮点数按照指定的要求转换成对应的字符串
|
||||
*
|
||||
* @param str 要返回的字符串
|
||||
* @param num 要打印的数值
|
||||
* @param field_width 区域宽度
|
||||
* @param precision 精度
|
||||
* @param flags 标志位
|
||||
*/
|
||||
|
||||
char pad, sign, tmp_num_z[100], tmp_num_d[350];
|
||||
|
||||
const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
// 显示小写字母
|
||||
if (flags & SMALL)
|
||||
digits = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
// 设置填充元素
|
||||
pad = (flags & PAD_ZERO) ? '0' : ' ';
|
||||
sign = 0;
|
||||
if (flags & SIGN && num < 0)
|
||||
{
|
||||
sign = '-';
|
||||
num = -num;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 设置符号
|
||||
sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
|
||||
}
|
||||
|
||||
// sign占用了一个宽度
|
||||
if (sign)
|
||||
--field_width;
|
||||
|
||||
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
|
||||
uint64_t num_z = (uint64_t)(num); // 获取整数部分
|
||||
uint64_t num_decimal = (uint64_t)(round(1.0 * (num - num_z) * pow(10, precision))); // 获取小数部分
|
||||
|
||||
if (num == 0 || num_z == 0)
|
||||
tmp_num_z[js_num_z++] = '0';
|
||||
else
|
||||
{
|
||||
//存储整数部分
|
||||
while (num_z > 0)
|
||||
{
|
||||
tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位
|
||||
num_z /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
while (num_decimal > 0)
|
||||
{
|
||||
tmp_num_d[js_num_d++] = digits[num_decimal % 10];
|
||||
num_decimal /= 10;
|
||||
}
|
||||
|
||||
field_width -= (precision + 1 + js_num_z);
|
||||
|
||||
// 靠右对齐
|
||||
if (!(flags & LEFT))
|
||||
while (field_width-- > 0)
|
||||
*str++ = pad;
|
||||
|
||||
if (sign)
|
||||
*str++ = sign;
|
||||
|
||||
// 输出整数部分
|
||||
// while (js_num_z-- > 0)
|
||||
// *str++ = tmp_num_z[js_num_z];
|
||||
while (js_num_z > 0)
|
||||
{
|
||||
*str++ = tmp_num_z[js_num_z - 1];
|
||||
--js_num_z;
|
||||
}
|
||||
*str++ = '.';
|
||||
|
||||
// 输出小数部分
|
||||
int total_dec_count = js_num_d;
|
||||
for (int i = 0; i < precision && js_num_d-- > 0; ++i)
|
||||
*str++ = tmp_num_d[js_num_d];
|
||||
|
||||
while (total_dec_count < precision)
|
||||
{
|
||||
++total_dec_count;
|
||||
*str++ = '0';
|
||||
}
|
||||
|
||||
while (field_width-- > 0)
|
||||
*str++ = ' ';
|
||||
|
||||
return str;
|
||||
}
|
13
user/libs/libc/src/printf.h
Normal file
13
user/libs/libc/src/printf.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#define PAD_ZERO 1 // 0填充
|
||||
#define LEFT 2 // 靠左对齐
|
||||
#define RIGHT 4 // 靠右对齐
|
||||
#define PLUS 8 // 在正数前面显示加号
|
||||
#define SPACE 16
|
||||
#define SPECIAL 32 // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
|
||||
#define SMALL 64 // 十进制以上数字显示小写字母
|
||||
#define SIGN 128 // 显示符号位
|
||||
|
||||
#define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏
|
13
user/libs/libc/src/stddef.h
Normal file
13
user/libs/libc/src/stddef.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define NULL 0
|
||||
#else
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t; // Signed integer type of the result of subtracting two pointers.
|
||||
|
35
user/libs/libc/src/stdio.h
Normal file
35
user/libs/libc/src/stdio.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <libc/src/sys/types.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
// 字体颜色的宏定义
|
||||
#define COLOR_WHITE 0x00ffffff //白
|
||||
#define COLOR_BLACK 0x00000000 //黑
|
||||
#define COLOR_RED 0x00ff0000 //红
|
||||
#define COLOR_ORANGE 0x00ff8000 //橙
|
||||
#define COLOR_YELLOW 0x00ffff00 //黄
|
||||
#define COLOR_GREEN 0x0000ff00 //绿
|
||||
#define COLOR_BLUE 0x000000ff //蓝
|
||||
#define COLOR_INDIGO 0x0000ffff //靛
|
||||
#define COLOR_PURPLE 0x008000ff //紫
|
||||
|
||||
#define SEEK_SET 0 /* Seek relative to start-of-file */
|
||||
#define SEEK_CUR 1 /* Seek relative to current position */
|
||||
#define SEEK_END 2 /* Seek relative to end-of-file */
|
||||
|
||||
#define SEEK_MAX 3
|
||||
|
||||
/**
|
||||
* @brief 往屏幕上输出字符串
|
||||
*
|
||||
* @param str 字符串指针
|
||||
* @param front_color 前景色
|
||||
* @param bg_color 背景色
|
||||
* @return int64_t
|
||||
*/
|
||||
int64_t put_string(char *str, uint64_t front_color, uint64_t bg_color);
|
||||
|
||||
int printf(const char *fmt, ...);
|
||||
int sprintf(char *buf, const char *fmt, ...);
|
||||
int vsprintf(char *buf, const char *fmt, va_list args);
|
57
user/libs/libc/src/stdlib.c
Normal file
57
user/libs/libc/src/stdlib.c
Normal file
@ -0,0 +1,57 @@
|
||||
#include <libc/src/unistd.h>
|
||||
#include <libc/src/stdlib.h>
|
||||
#include <libc/src/ctype.h>
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
int abs(int i)
|
||||
{
|
||||
return i < 0 ? -i : i;
|
||||
}
|
||||
|
||||
long labs(long i)
|
||||
{
|
||||
return i < 0 ? -i : i;
|
||||
}
|
||||
|
||||
long long llabs(long long i)
|
||||
{
|
||||
return i < 0 ? -i : i;
|
||||
}
|
||||
|
||||
int atoi(const char *str)
|
||||
{
|
||||
int n = 0, neg = 0;
|
||||
|
||||
while (isspace(*str))
|
||||
{
|
||||
str++;
|
||||
}
|
||||
|
||||
switch (*str)
|
||||
{
|
||||
case '-':
|
||||
neg = 1;
|
||||
break;
|
||||
case '+':
|
||||
str++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Compute n as a negative number to avoid overflow on INT_MIN */
|
||||
while (isdigit(*str))
|
||||
{
|
||||
n = 10 * n - (*str++ - '0');
|
||||
}
|
||||
|
||||
return neg ? n : -n;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 退出进程
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
void exit(int status)
|
||||
{
|
||||
syscall_invoke(SYS_EXIT, status, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
42
user/libs/libc/src/stdlib.h
Normal file
42
user/libs/libc/src/stdlib.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief 获取一块堆内存
|
||||
*
|
||||
* @param size 内存大小
|
||||
* @return void* 内存空间的指针
|
||||
*/
|
||||
void *malloc(ssize_t size);
|
||||
|
||||
/**
|
||||
* @brief 释放一块堆内存
|
||||
*
|
||||
* @param ptr 堆内存的指针
|
||||
*/
|
||||
void free(void* ptr);
|
||||
|
||||
/**
|
||||
* @brief 返回int的绝对值
|
||||
*
|
||||
* @param i
|
||||
* @return int
|
||||
*/
|
||||
int abs(int i);
|
||||
long labs(long i);
|
||||
long long llabs(long long i);
|
||||
|
||||
/**
|
||||
* @brief 字符串转int
|
||||
*
|
||||
* @param str
|
||||
* @return int
|
||||
*/
|
||||
int atoi(const char * str);
|
||||
|
||||
/**
|
||||
* @brief 退出进程
|
||||
*
|
||||
* @param status
|
||||
*/
|
||||
void exit(int status);
|
116
user/libs/libc/src/string.c
Normal file
116
user/libs/libc/src/string.c
Normal file
@ -0,0 +1,116 @@
|
||||
#include "string.h"
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
register int __res = 0;
|
||||
while (s[__res] != '\0')
|
||||
{
|
||||
++__res;
|
||||
}
|
||||
return __res;
|
||||
}
|
||||
|
||||
int strcmp(const char *FirstPart, const char *SecondPart)
|
||||
{
|
||||
register int __res;
|
||||
__asm__ __volatile__("cld \n\t"
|
||||
"1: \n\t"
|
||||
"lodsb \n\t"
|
||||
"scasb \n\t"
|
||||
"jne 2f \n\t"
|
||||
"testb %%al, %%al \n\t"
|
||||
"jne 1b \n\t"
|
||||
"xorl %%eax, %%eax \n\t"
|
||||
"jmp 3f \n\t"
|
||||
"2: \n\t"
|
||||
"movl $1, %%eax \n\t"
|
||||
"jl 3f \n\t"
|
||||
"negl %%eax \n\t"
|
||||
"3: \n\t"
|
||||
: "=a"(__res)
|
||||
: "D"(FirstPart), "S"(SecondPart)
|
||||
:);
|
||||
return __res;
|
||||
}
|
||||
|
||||
void *memset(void *dst, unsigned char C, uint64_t size)
|
||||
{
|
||||
|
||||
int d0, d1;
|
||||
unsigned long tmp = C * 0x0101010101010101UL;
|
||||
__asm__ __volatile__("cld \n\t"
|
||||
"rep \n\t"
|
||||
"stosq \n\t"
|
||||
"testb $4, %b3 \n\t"
|
||||
"je 1f \n\t"
|
||||
"stosl \n\t"
|
||||
"1:\ttestb $2, %b3 \n\t"
|
||||
"je 2f\n\t"
|
||||
"stosw \n\t"
|
||||
"2:\ttestb $1, %b3 \n\t"
|
||||
"je 3f \n\t"
|
||||
"stosb \n\t"
|
||||
"3: \n\t"
|
||||
: "=&c"(d0), "=&D"(d1)
|
||||
: "a"(tmp), "q"(size), "0"(size / 8), "1"(dst)
|
||||
: "memory");
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拷贝指定字节数的字符串
|
||||
*
|
||||
* @param dst 目标地址
|
||||
* @param src 源字符串
|
||||
* @param Count 字节数
|
||||
* @return char*
|
||||
*/
|
||||
char *strncpy(char *dst, const char *src, size_t Count)
|
||||
{
|
||||
__asm__ __volatile__("cld \n\t"
|
||||
"1: \n\t"
|
||||
"decq %2 \n\t"
|
||||
"js 2f \n\t"
|
||||
"lodsb \n\t"
|
||||
"stosb \n\t"
|
||||
"testb %%al, %%al \n\t"
|
||||
"jne 1b \n\t"
|
||||
"rep \n\t"
|
||||
"stosb \n\t"
|
||||
"2: \n\t"
|
||||
:
|
||||
: "S"(src), "D"(dst), "c"(Count)
|
||||
: "ax", "memory");
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拼接两个字符串(将src接到dest末尾)
|
||||
*
|
||||
* @param dest 目标串
|
||||
* @param src 源串
|
||||
* @return char*
|
||||
*/
|
||||
char *strcat(char *dest, const char *src)
|
||||
{
|
||||
strcpy(dest + strlen(dest), src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 拷贝整个字符串
|
||||
*
|
||||
* @param dst 目标地址
|
||||
* @param src 源地址
|
||||
* @return char* 目标字符串
|
||||
*/
|
||||
char *strcpy(char *dst, const char *src)
|
||||
{
|
||||
while (*src)
|
||||
{
|
||||
*(dst++) = *(src++);
|
||||
}
|
||||
*dst = 0;
|
||||
|
||||
return dst;
|
||||
}
|
79
user/libs/libc/src/string.h
Normal file
79
user/libs/libc/src/string.h
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
void *memset(void *dst, unsigned char C, uint64_t size);
|
||||
/**
|
||||
* @brief 获取字符串的大小
|
||||
*
|
||||
* @param s 字符串
|
||||
* @return size_t 大小
|
||||
*/
|
||||
size_t strlen(const char *s);
|
||||
|
||||
/*
|
||||
比较字符串 FirstPart and SecondPart
|
||||
FirstPart = SecondPart => 0
|
||||
FirstPart > SecondPart => 1
|
||||
FirstPart < SecondPart => -1
|
||||
*/
|
||||
|
||||
int strcmp(const char *FirstPart, const char *SecondPart);
|
||||
|
||||
/**
|
||||
* @brief 拷贝指定字节数的字符串
|
||||
*
|
||||
* @param dst 目标地址
|
||||
* @param src 源字符串
|
||||
* @param Count 字节数
|
||||
* @return char*
|
||||
*/
|
||||
char *strncpy(char *dst, const char *src, size_t Count);
|
||||
|
||||
/**
|
||||
* @brief 拷贝整个字符串
|
||||
*
|
||||
* @param dst 目标地址
|
||||
* @param src 源地址
|
||||
* @return char* 目标字符串
|
||||
*/
|
||||
char* strcpy(char* dst, const char* src);
|
||||
|
||||
/**
|
||||
* @brief 拼接两个字符串(将src接到dest末尾)
|
||||
*
|
||||
* @param dest 目标串
|
||||
* @param src 源串
|
||||
* @return char*
|
||||
*/
|
||||
char *strcat(char *dest, const char *src);
|
||||
|
||||
/**
|
||||
* @brief 内存拷贝函数
|
||||
*
|
||||
* @param dst 目标数组
|
||||
* @param src 源数组
|
||||
* @param Num 字节数
|
||||
* @return void*
|
||||
*/
|
||||
static void *memcpy(void *dst, const void *src, long Num)
|
||||
{
|
||||
int d0 = 0, d1 = 0, d2 = 0;
|
||||
__asm__ __volatile__("cld \n\t"
|
||||
"rep \n\t"
|
||||
"movsq \n\t"
|
||||
"testb $4,%b4 \n\t"
|
||||
"je 1f \n\t"
|
||||
"movsl \n\t"
|
||||
"1:\ttestb $2,%b4 \n\t"
|
||||
"je 2f \n\t"
|
||||
"movsw \n\t"
|
||||
"2:\ttestb $1,%b4 \n\t"
|
||||
"je 3f \n\t"
|
||||
"movsb \n\t"
|
||||
"3: \n\t"
|
||||
: "=&c"(d0), "=&D"(d1), "=&S"(d2)
|
||||
: "0"(Num / 8), "q"(Num), "1"(dst), "2"(src)
|
||||
: "memory");
|
||||
return dst;
|
||||
}
|
11
user/libs/libc/src/sys/Makefile
Normal file
11
user/libs/libc/src/sys/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
all: wait.o stat.o
|
||||
|
||||
CFLAGS += -I .
|
||||
|
||||
|
||||
wait.o: wait.c
|
||||
$(CC) $(CFLAGS) -c wait.c -o wait.o
|
||||
|
||||
stat.o: stat.c
|
||||
$(CC) $(CFLAGS) -c stat.c -o stat.o
|
23
user/libs/libc/src/sys/stat.c
Normal file
23
user/libs/libc/src/sys/stat.c
Normal file
@ -0,0 +1,23 @@
|
||||
#include "stat.h"
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
int mkdir(const char *path, mode_t mode)
|
||||
{
|
||||
return syscall_invoke(SYS_MKDIR, (uint64_t)path, (uint64_t)mode, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取系统的内存信息
|
||||
*
|
||||
* @param stat 传入的内存信息结构体
|
||||
* @return int 错误码
|
||||
*/
|
||||
int mstat(struct mstat_t *stat)
|
||||
{
|
||||
return syscall_invoke(SYS_MSTAT, (uint64_t)stat, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
int pipe(int *fd)
|
||||
{
|
||||
return syscall_invoke(SYS_PIPE, (uint64_t)fd, 0, 0,0,0,0,0,0);
|
||||
}
|
28
user/libs/libc/src/sys/stat.h
Normal file
28
user/libs/libc/src/sys/stat.h
Normal file
@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief 系统内存信息结构体(单位:字节)
|
||||
*
|
||||
*/
|
||||
struct mstat_t
|
||||
{
|
||||
uint64_t total; // 计算机的总内存数量大小
|
||||
uint64_t used; // 已使用的内存大小
|
||||
uint64_t free; // 空闲物理页所占的内存大小
|
||||
uint64_t shared; // 共享的内存大小
|
||||
uint64_t cache_used; // 位于slab缓冲区中的已使用的内存大小
|
||||
uint64_t cache_free; // 位于slab缓冲区中的空闲的内存大小
|
||||
uint64_t available; // 系统总空闲内存大小(包括kmalloc缓冲区)
|
||||
};
|
||||
|
||||
int mkdir(const char *path, mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief 获取系统的内存信息
|
||||
*
|
||||
* @param stat 传入的内存信息结构体
|
||||
* @return int 错误码
|
||||
*/
|
||||
int mstat(struct mstat_t* stat);
|
||||
int pipe(int *fd);
|
83
user/libs/libc/src/sys/types.h
Normal file
83
user/libs/libc/src/sys/types.h
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef unsigned char u_char;
|
||||
typedef unsigned short u_short;
|
||||
typedef unsigned int u_int;
|
||||
typedef unsigned long u_long;
|
||||
|
||||
typedef uint32_t uid_t;
|
||||
typedef uint32_t gid_t;
|
||||
typedef long long ssize_t;
|
||||
|
||||
typedef int64_t pid_t;
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
||||
typedef char *caddr_t;
|
||||
|
||||
typedef int id_t;
|
||||
|
||||
typedef uint64_t ino_t;
|
||||
typedef int64_t off_t;
|
||||
|
||||
typedef uint32_t blkcnt_t;
|
||||
typedef uint32_t blksize_t;
|
||||
typedef uint32_t dev_t;
|
||||
typedef uint16_t mode_t;
|
||||
typedef uint32_t nlink_t;
|
||||
|
||||
typedef int64_t time_t;
|
||||
typedef uint32_t useconds_t;
|
||||
typedef int32_t suseconds_t;
|
||||
typedef uint32_t clock_t;
|
||||
|
||||
typedef uint64_t fsblkcnt_t;
|
||||
typedef uint64_t fsfilcnt_t;
|
||||
|
||||
#define __socklen_t_defined
|
||||
#define __socklen_t uint32_t
|
||||
typedef __socklen_t socklen_t;
|
||||
|
||||
struct utimbuf
|
||||
{
|
||||
time_t actime;
|
||||
time_t modtime;
|
||||
};
|
||||
|
||||
typedef int pthread_t;
|
||||
typedef int pthread_key_t;
|
||||
typedef uint32_t pthread_once_t;
|
||||
|
||||
typedef struct __pthread_mutex_t
|
||||
{
|
||||
uint32_t lock;
|
||||
pthread_t owner;
|
||||
int level;
|
||||
int type;
|
||||
} pthread_mutex_t;
|
||||
|
||||
typedef void *pthread_attr_t;
|
||||
typedef struct __pthread_mutexattr_t
|
||||
{
|
||||
int type;
|
||||
} pthread_mutexattr_t;
|
||||
|
||||
typedef struct __pthread_cond_t
|
||||
{
|
||||
pthread_mutex_t *mutex;
|
||||
uint32_t value;
|
||||
int clockid; // clockid_t
|
||||
} pthread_cond_t;
|
||||
|
||||
typedef uint64_t pthread_rwlock_t;
|
||||
typedef void *pthread_rwlockattr_t;
|
||||
typedef struct __pthread_spinlock_t
|
||||
{
|
||||
int m_lock;
|
||||
} pthread_spinlock_t;
|
||||
typedef struct __pthread_condattr_t
|
||||
{
|
||||
int clockid; // clockid_t
|
||||
} pthread_condattr_t;
|
26
user/libs/libc/src/sys/wait.c
Normal file
26
user/libs/libc/src/sys/wait.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "wait.h"
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
/**
|
||||
* @brief 等待所有子进程退出
|
||||
*
|
||||
* @param stat_loc 返回的子进程结束状态
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t wait(int *stat_loc)
|
||||
{
|
||||
return waitpid((pid_t)(-1), stat_loc, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 等待指定pid的子进程退出
|
||||
*
|
||||
* @param pid 子进程的pid
|
||||
* @param stat_loc 返回的子进程结束状态
|
||||
* @param options 额外的控制选项
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t waitpid(pid_t pid, int *stat_loc, int options)
|
||||
{
|
||||
return (pid_t)syscall_invoke(SYS_WAIT4, (uint64_t)pid, (uint64_t)stat_loc, options, 0, 0, 0, 0, 0);
|
||||
}
|
21
user/libs/libc/src/sys/wait.h
Normal file
21
user/libs/libc/src/sys/wait.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.h"
|
||||
|
||||
/**
|
||||
* @brief 等待所有子进程退出
|
||||
*
|
||||
* @param stat_loc 返回的子进程结束状态
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t wait(int *stat_loc);
|
||||
|
||||
/**
|
||||
* @brief 等待指定pid的子进程退出
|
||||
*
|
||||
* @param pid 子进程的pid
|
||||
* @param stat_loc 返回的子进程结束状态
|
||||
* @param options 额外的控制选项
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t waitpid(pid_t pid, int *stat_loc, int options);
|
12
user/libs/libc/src/sysdeps/x86_64/Makefile
Normal file
12
user/libs/libc/src/sysdeps/x86_64/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
|
||||
all: start.o
|
||||
|
||||
ifeq ($(ARCH), __x86_64__)
|
||||
start.o:
|
||||
$(CC) $(CFLAGS) -c elf/start.c -o elf/start.o
|
||||
endif
|
||||
|
||||
clean:
|
||||
|
||||
echo "Done."
|
13
user/libs/libc/src/sysdeps/x86_64/elf/start.c
Normal file
13
user/libs/libc/src/sysdeps/x86_64/elf/start.c
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
#include <libc/src/stdio.h>
|
||||
#include <libc/src/stdlib.h>
|
||||
|
||||
extern int main(int, char **);
|
||||
|
||||
void _start(int argc, char **argv)
|
||||
{
|
||||
// printf("before main\n");
|
||||
int retval = main(argc, argv);
|
||||
// printf("before exit, code=%d\n", retval);
|
||||
exit(retval);
|
||||
}
|
42
user/libs/libc/src/time.c
Normal file
42
user/libs/libc/src/time.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "time.h"
|
||||
#include "errno.h"
|
||||
#include "unistd.h"
|
||||
#include <libsystem/syscall.h>
|
||||
|
||||
/**
|
||||
* @brief 休眠指定时间
|
||||
*
|
||||
* @param rqtp 指定休眠的时间
|
||||
* @param rmtp 返回的剩余休眠时间
|
||||
* @return int
|
||||
*/
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||
{
|
||||
return syscall_invoke(SYS_NANOSLEEP, (uint64_t)rqtp, (uint64_t)rmtp, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 睡眠指定时间
|
||||
*
|
||||
* @param usec 微秒
|
||||
* @return int
|
||||
*/
|
||||
int usleep(useconds_t usec)
|
||||
{
|
||||
struct timespec ts = {
|
||||
tv_sec : (long int)(usec / 1000000),
|
||||
tv_nsec : (long int)(usec % 1000000) * 1000UL
|
||||
};
|
||||
|
||||
return nanosleep(&ts, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取系统当前cpu时间
|
||||
*
|
||||
* @return clock_t
|
||||
*/
|
||||
clock_t clock()
|
||||
{
|
||||
return (clock_t)syscall_invoke(SYS_CLOCK, 0,0,0,0,0,0,0,0);
|
||||
}
|
45
user/libs/libc/src/time.h
Normal file
45
user/libs/libc/src/time.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "stddef.h"
|
||||
|
||||
// 操作系统定义时间以ns为单位
|
||||
#define CLOCKS_PER_SEC 1000000
|
||||
|
||||
struct tm
|
||||
{
|
||||
int tm_sec; /* Seconds. [0-60] (1 leap second) */
|
||||
int tm_min; /* Minutes. [0-59] */
|
||||
int tm_hour; /* Hours. [0-23] */
|
||||
int tm_mday; /* Day. [1-31] */
|
||||
int tm_mon; /* Month. [0-11] */
|
||||
int tm_year; /* Year - 1900. */
|
||||
int tm_wday; /* Day of week. [0-6] */
|
||||
int tm_yday; /* Days in year.[0-365] */
|
||||
int tm_isdst; /* DST. [-1/0/1]*/
|
||||
|
||||
long int __tm_gmtoff; /* Seconds east of UTC. */
|
||||
const char *__tm_zone; /* Timezone abbreviation. */
|
||||
};
|
||||
|
||||
|
||||
struct timespec
|
||||
{
|
||||
long int tv_sec; // 秒
|
||||
long int tv_nsec; // 纳秒
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief 休眠指定时间
|
||||
*
|
||||
* @param rqtp 指定休眠的时间
|
||||
* @param rmtp 返回的剩余休眠时间
|
||||
* @return int
|
||||
*/
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
|
||||
|
||||
/**
|
||||
* @brief 获取系统当前cpu时间
|
||||
*
|
||||
* @return clock_t
|
||||
*/
|
||||
clock_t clock();
|
196
user/libs/libc/src/unistd.c
Normal file
196
user/libs/libc/src/unistd.c
Normal file
@ -0,0 +1,196 @@
|
||||
#include <libc/src/unistd.h>
|
||||
#include <libsystem/syscall.h>
|
||||
#include <libc/src/errno.h>
|
||||
#include <libc/src/stdio.h>
|
||||
#include <libc/src/stddef.h>
|
||||
#include <libc/src/string.h>
|
||||
#include <libc/src/fcntl.h>
|
||||
|
||||
/**
|
||||
* @brief 关闭文件接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @return int
|
||||
*/
|
||||
int close(int fd)
|
||||
{
|
||||
return syscall_invoke(SYS_CLOSE, fd, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从文件读取数据的接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @param buf 缓冲区
|
||||
* @param count 待读取数据的字节数
|
||||
* @return ssize_t 成功读取的字节数
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t count)
|
||||
{
|
||||
return (ssize_t)syscall_invoke(SYS_READ, fd, (uint64_t)buf, count, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 向文件写入数据的接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @param buf 缓冲区
|
||||
* @param count 待写入数据的字节数
|
||||
* @return ssize_t 成功写入的字节数
|
||||
*/
|
||||
ssize_t write(int fd, void const *buf, size_t count)
|
||||
{
|
||||
return (ssize_t)syscall_invoke(SYS_WRITE, fd, (uint64_t)buf, count, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 调整文件的访问位置
|
||||
*
|
||||
* @param fd 文件描述符号
|
||||
* @param offset 偏移量
|
||||
* @param whence 调整模式
|
||||
* @return uint64_t 调整结束后的文件访问位置
|
||||
*/
|
||||
off_t lseek(int fd, off_t offset, int whence)
|
||||
{
|
||||
return (off_t)syscall_invoke(SYS_LSEEK, fd, offset, whence, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fork当前进程
|
||||
*
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t fork(void)
|
||||
{
|
||||
return (pid_t)syscall_invoke(SYS_FORK, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief fork当前进程,但是与父进程共享VM、flags、fd
|
||||
*
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t vfork(void)
|
||||
{
|
||||
return (pid_t)syscall_invoke(SYS_VFORK, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将堆内存调整为end_brk
|
||||
*
|
||||
* @param end_brk 新的堆区域的结束地址
|
||||
* end_brk=-1 ===> 返回堆区域的起始地址
|
||||
* end_brk=-2 ===> 返回堆区域的结束地址
|
||||
* @return uint64_t 错误码
|
||||
*
|
||||
*/
|
||||
uint64_t brk(uint64_t end_brk)
|
||||
{
|
||||
uint64_t x = (uint64_t)syscall_invoke(SYS_BRK, (uint64_t)end_brk, 0, 0, 0, 0, 0, 0, 0);
|
||||
// printf("brk(): end_brk=%#018lx x=%#018lx", (uint64_t)end_brk, x);
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程)
|
||||
*
|
||||
* @param increment offset偏移量
|
||||
* @return uint64_t the previous program break
|
||||
*/
|
||||
void *sbrk(int64_t increment)
|
||||
{
|
||||
void *retval = (void *)syscall_invoke(SYS_SBRK, (uint64_t)increment, 0, 0, 0, 0, 0, 0, 0);
|
||||
if (retval == (void *)-ENOMEM)
|
||||
return (void *)(-1);
|
||||
else
|
||||
{
|
||||
errno = 0;
|
||||
return (void *)retval;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 切换当前工作目录
|
||||
*
|
||||
* @param dest_path 目标目录
|
||||
* @return int64_t 成功:0,失败:负值(错误码)
|
||||
*/
|
||||
int64_t chdir(char *dest_path)
|
||||
{
|
||||
if (dest_path == NULL)
|
||||
{
|
||||
errno = -EFAULT;
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return syscall_invoke(SYS_CHDIR, (uint64_t)dest_path, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 执行新的程序
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param argv 参数列表
|
||||
* @return int
|
||||
*/
|
||||
int execv(const char *path, char *const argv[])
|
||||
{
|
||||
if (path == NULL)
|
||||
{
|
||||
errno = -ENOENT;
|
||||
return -1;
|
||||
}
|
||||
int retval = syscall_invoke(SYS_EXECVE, (uint64_t)path, (uint64_t)argv, 0, 0, 0, 0, 0, 0);
|
||||
if (retval != 0)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除文件夹
|
||||
*
|
||||
* @param path 绝对路径
|
||||
* @return int 错误码
|
||||
*/
|
||||
int rmdir(const char *path)
|
||||
{
|
||||
return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, AT_REMOVEDIR, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 删除文件
|
||||
*
|
||||
* @param path 绝对路径
|
||||
* @return int
|
||||
*/
|
||||
int rm(const char * path)
|
||||
{
|
||||
return syscall_invoke(SYS_UNLINK_AT, 0, (uint64_t)path, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 交换n字节
|
||||
* @param src 源地址
|
||||
* @param dest 目的地址
|
||||
* @param nbytes 交换字节数
|
||||
*/
|
||||
void swab(void *restrict src, void *restrict dest, ssize_t nbytes)
|
||||
{
|
||||
unsigned char buf[32];
|
||||
char *_src = src;
|
||||
char *_dest = dest;
|
||||
uint32_t transfer;
|
||||
for (; nbytes > 0; nbytes -= transfer)
|
||||
{
|
||||
transfer = (nbytes > 32) ? 32 : nbytes;
|
||||
memcpy(buf, _src, transfer);
|
||||
memcpy(_src, _dest, transfer);
|
||||
memcpy(_dest, buf, transfer);
|
||||
_src += transfer;
|
||||
_dest += transfer;
|
||||
}
|
||||
}
|
117
user/libs/libc/src/unistd.h
Normal file
117
user/libs/libc/src/unistd.h
Normal file
@ -0,0 +1,117 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <libc/src/sys/types.h>
|
||||
|
||||
/**
|
||||
* @brief 关闭文件接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @return int
|
||||
*/
|
||||
int close(int fd);
|
||||
|
||||
/**
|
||||
* @brief 从文件读取数据的接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @param buf 缓冲区
|
||||
* @param count 待读取数据的字节数
|
||||
* @return ssize_t 成功读取的字节数
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief 向文件写入数据的接口
|
||||
*
|
||||
* @param fd 文件描述符
|
||||
* @param buf 缓冲区
|
||||
* @param count 待写入数据的字节数
|
||||
* @return ssize_t 成功写入的字节数
|
||||
*/
|
||||
ssize_t write(int fd, void const *buf, size_t count);
|
||||
|
||||
/**
|
||||
* @brief 调整文件的访问位置
|
||||
*
|
||||
* @param fd 文件描述符号
|
||||
* @param offset 偏移量
|
||||
* @param whence 调整模式
|
||||
* @return uint64_t 调整结束后的文件访问位置
|
||||
*/
|
||||
off_t lseek(int fd, off_t offset, int whence);
|
||||
|
||||
/**
|
||||
* @brief fork当前进程
|
||||
*
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t fork(void);
|
||||
|
||||
/**
|
||||
* @brief fork当前进程,但是与父进程共享VM、flags、fd
|
||||
*
|
||||
* @return pid_t
|
||||
*/
|
||||
pid_t vfork(void);
|
||||
|
||||
/**
|
||||
* @brief 将堆内存调整为end_brk
|
||||
*
|
||||
* @param end_brk 新的堆区域的结束地址
|
||||
* end_brk=-1 ===> 返回堆区域的起始地址
|
||||
* end_brk=-2 ===> 返回堆区域的结束地址
|
||||
* @return uint64_t 错误码
|
||||
*
|
||||
*/
|
||||
uint64_t brk(uint64_t end_brk);
|
||||
|
||||
/**
|
||||
* @brief 将堆内存空间加上offset(注意,该系统调用只应在普通进程中调用,而不能是内核线程)
|
||||
*
|
||||
* @param increment offset偏移量
|
||||
* @return uint64_t the previous program break
|
||||
*/
|
||||
void *sbrk(int64_t increment);
|
||||
|
||||
/**
|
||||
* @brief 切换当前工作目录
|
||||
*
|
||||
* @param dest_path 目标目录
|
||||
* @return int64_t 成功:0,失败:负值(错误码)
|
||||
*/
|
||||
int64_t chdir(char *dest_path);
|
||||
|
||||
/**
|
||||
* @brief 执行新的程序
|
||||
*
|
||||
* @param path 文件路径
|
||||
* @param argv 参数列表
|
||||
* @return int
|
||||
*/
|
||||
int execv(const char *path, char *const argv[]);
|
||||
|
||||
/**
|
||||
* @brief 睡眠指定时间
|
||||
*
|
||||
* @param usec 微秒
|
||||
* @return int
|
||||
*/
|
||||
extern int usleep(useconds_t usec);
|
||||
|
||||
/**
|
||||
* @brief 删除文件夹
|
||||
*
|
||||
* @param path 绝对路径
|
||||
* @return int 错误码
|
||||
*/
|
||||
int rmdir(const char *path);
|
||||
|
||||
int rm(const char * path);
|
||||
|
||||
/**
|
||||
* @brief 交换n字节
|
||||
* @param src 源地址
|
||||
* @param dest 目的地址
|
||||
* @param nbytes 交换字节数
|
||||
*/
|
||||
void swab(void *restrict src, void *restrict dest, ssize_t nbytes);
|
15
user/libs/libc/src/x86_64-unknown-none.json
Normal file
15
user/libs/libc/src/x86_64-unknown-none.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"llvm-target": "x86_64-unknown-none",
|
||||
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
|
||||
"arch": "x86_64",
|
||||
"target-endian": "little",
|
||||
"target-pointer-width": "64",
|
||||
"target-c-int-width": "32",
|
||||
"os": "none",
|
||||
"linker": "rust-lld",
|
||||
"linker-flavor": "ld.lld",
|
||||
"executables": true,
|
||||
"features": "-mmx,-sse,+soft-float",
|
||||
"disable-redzone": true,
|
||||
"panic-strategy": "abort"
|
||||
}
|
Reference in New Issue
Block a user