void** index; // fast reference, to accelerate access to this very region.
void* data;
- // When a page is mapped and required initialize
- int (*init_page)(struct mm_region*, void*, off_t);
// when a region is copied
void (*region_copied)(struct mm_region*);
// when a region is unmapped
#define V2P(vaddr) ((ptr_t)(vaddr)-KERNEL_MM_BASE)
#define PG_ALIGN(addr) ((ptr_t)(addr)&0xFFFFF000UL)
+#define PG_MOD(addr) ((ptr_t)(addr) & ~PG_SIZE)
#define PG_ALIGNED(addr) (!((ptr_t)(addr)&0x00000FFFUL))
#define L1_INDEX(vaddr) (u32_t)(((ptr_t)(vaddr)&0xFFC00000UL) >> 22)
ptr = PG_ALIGN(ptr);
- u32_t offset = (ptr - hit_region->start) + hit_region->foff;
+ u32_t mseg_off = (ptr - hit_region->start);
+ u32_t mfile_off = mseg_off + hit_region->foff;
uintptr_t pa = pmm_alloc_page(__current->pid, 0);
if (!pa) {
memset(ptr, 0, PG_SIZE);
int errno = 0;
- if (hit_region->init_page) {
- errno = hit_region->init_page(hit_region, ptr, offset);
- } else {
- errno = file->ops->read_page(file->inode, ptr, PG_SIZE, offset);
+ if (mseg_off < hit_region->flen) {
+ errno = file->ops->read_page(file->inode, ptr, PG_SIZE, mfile_off);
}
if (errno < 0) {
case, our rootfs will be something like ext2.
RamFS vs. TwiFS: Indeed, they are both fs that lives in RAM so
- there is no foundmentally differences. However, TwiFS is designed
+ there is no foundmental differences. However, TwiFS is designed
to be a 'virtual FIlesystem for KERnel space' (FIKER), so other
kernel sub-modules can just create node and attach their own
implementation of read/write, without brothering to create a
size_t cpy_size = MIN(dnode->name.len, size - len);
strncpy(buf + len, dnode->name.value, cpy_size);
- len += cpy_size;
+ len += cpy_size + !!cpy_size;
return len;
}
}
}
- buf[len + 1] = '\0';
+ buf[len] = '\0';
ret_ptr = buf;
#include <lunaix/mm/vmm.h>
#include <lunaix/spike.h>
-int
-__elf_populate_mapped(struct mm_region* region, void* pg, off_t segfoff)
-{
- size_t segsz = region->flen;
- size_t segmoff = segfoff - region->foff;
-
- if (segmoff >= segsz) {
- return 0;
- }
-
- struct v_file* file = region->mfile;
- size_t rdlen = MIN(segsz - segmoff, PG_SIZE);
-
- if (rdlen == PG_SIZE) {
- // This is because we want to exploit any optimization on read_page
- return file->ops->read_page(file->inode, pg, PG_SIZE, segfoff);
- } else {
- // we don't want to over-read the segment!
- return file->ops->read(file->inode, pg, rdlen, segfoff);
- }
-}
-
int
elf_map_segment(struct ld_param* ldparam,
struct v_file* elfile,
struct elf32_phdr* phdr)
{
+ assert(PG_ALIGNED(phdr->p_offset));
+
int proct = 0;
if ((phdr->p_flags & PF_R)) {
proct |= PROT_READ;
proct |= PROT_EXEC;
}
- struct mm_region* seg_reg;
struct mmap_param param = { .vms_mnt = ldparam->vms_mnt,
.pvms = &ldparam->proc->mm,
.proct = proct,
- .offset = phdr->p_offset,
+ .offset = PG_ALIGN(phdr->p_offset),
.mlen = ROUNDUP(phdr->p_memsz, PG_SIZE),
- .flen = phdr->p_filesz,
+ .flen = phdr->p_filesz + PG_MOD(phdr->p_va),
.flags = MAP_FIXED | MAP_PRIVATE,
.type = REGION_TYPE_CODE };
+ struct mm_region* seg_reg;
int status = mem_map(NULL, &seg_reg, PG_ALIGN(phdr->p_va), elfile, ¶m);
if (!status) {
- seg_reg->init_page = __elf_populate_mapped;
-
size_t next_addr = phdr->p_memsz + phdr->p_va;
ldparam->info.end = MAX(ldparam->info.end, ROUNDUP(next_addr, PG_SIZE));
ldparam->info.mem_sz += phdr->p_memsz;
.info = param->info };
} else {
// TODO need to find a way to inject argv and envp remotely
+ // this is for the support of kernel level implementation of
+ // posix_spawn
fail("not implemented");
}
return 0;
}
+int
+mem_remap(void** addr_out,
+ struct mm_region** remapped,
+ void* addr,
+ struct v_file* file,
+ struct mmap_param* param)
+{
+}
+
void
mem_sync_pages(ptr_t mnt,
struct mm_region* region,
if (!addr) {
addr = UMMAP_START;
} else if (addr < UMMAP_START || addr + length >= UMMAP_END) {
- errno = ENOMEM;
- goto done;
+ if (!(options & (MAP_FIXED | MAP_FIXED_NOREPLACE))) {
+ errno = ENOMEM;
+ goto done;
+ }
}
struct v_fd* vfd;
[_SIGINT] = default_sighandler_term,
};
-volatile struct proc_sigstate __temp_save;
// Referenced in kernel/asm/x86/interrupt.S
void*
signal_dispatch()
解决办法就是先吧intr_ctx拷贝到一个静态分配的区域里,然后再注入到用户栈。
*/
+ static volatile struct proc_sigstate __temp_save;
__temp_save.proc_regs = __current->intr_ctx;
memcpy(__temp_save.fxstate, __current->fxstate, 512);
+/**
+ * @file lxconsole.c
+ * @author Lunaixsky (lunaxisky@qq.com)
+ * @brief Provides simple terminal support
+ * @version 0.1
+ * @date 2023-06-18
+ *
+ * @copyright Copyright (c) 2023
+ *
+ */
+
#include <klibc/string.h>
#include <lunaix/device.h>
#include <lunaix/input.h>
}
__usrtext_end = ALIGN(4K);
- .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {
- build/obj/kernel/*.o (.bss)
- build/obj/hal/*.o (.bss)
- }
-
.data BLOCK(4k) : AT ( ADDR(.data) - 0xC0000000 ) {
build/obj/kernel/*.o (.data)
build/obj/hal/*.o (.data)
build/obj/arch/x86/*.o (.kpg)
}
+ .bss BLOCK(4K) : AT ( ADDR(.bss) - 0xC0000000 ) {
+ build/obj/kernel/*.o (.bss)
+ build/obj/hal/*.o (.bss)
+ }
+
__kernel_end = ALIGN(4K);
}
\ No newline at end of file
pid_t pid;
if (!(pid = fork())) {
- int err = execve("/mnt/lunaix-os/usr/ls", NULL, NULL);
+ int err = execve("/mnt/lunaix-os/usr/sh", NULL, NULL);
printf("fail to execute (%d)\n", err);
_exit(err);
}
--- /dev/null
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+char pwd[512];
+char cat_buf[1024];
+
+/*
+ Simple shell - (actually this is not even a shell)
+ It just to make the testing more easy.
+*/
+
+#define WS_CHAR(c) \
+ (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
+
+void
+strrtrim(char* str)
+{
+ size_t l = strlen(str);
+ while (l < (size_t)-1) {
+ char c = str[l];
+ if (!c || WS_CHAR(c)) {
+ l--;
+ continue;
+ }
+ break;
+ }
+ str[l + 1] = '\0';
+}
+
+char*
+strltrim_safe(char* str)
+{
+ size_t l = 0;
+ char c = 0;
+ while ((c = str[l]) && WS_CHAR(c)) {
+ l++;
+ }
+
+ if (!l)
+ return str;
+ return strcpy(str, str + l);
+}
+
+void
+parse_cmdline(char* line, char** cmd, char** arg_part)
+{
+ strrtrim(line);
+ line = strltrim_safe(line);
+ int l = 0;
+ char c = 0;
+ while ((c = line[l])) {
+ if (c == ' ') {
+ line[l++] = 0;
+ break;
+ }
+ l++;
+ }
+ *cmd = line;
+ *arg_part = strltrim_safe(line + l);
+}
+
+void
+sh_printerr()
+{
+ switch (errno) {
+ case 0:
+ break;
+ case ENOTDIR:
+ printf("Error: Not a directory\n");
+ break;
+ case ENOENT:
+ printf("Error: No such file or directory\n");
+ break;
+ case EINVAL:
+ printf("Error: Invalid parameter or operation\n");
+ break;
+ case ENOTSUP:
+ printf("Error: Not supported\n");
+ break;
+ case EROFS:
+ printf("Error: File system is read only\n");
+ break;
+ case ENOMEM:
+ printf("Error: Out of memory\n");
+ break;
+ case EISDIR:
+ printf("Error: This is a directory\n");
+ break;
+ default:
+ printf("Error: (%d)\n", errno);
+ break;
+ }
+}
+
+void
+sigint_handle(int signum)
+{
+ return;
+}
+
+void
+sh_exec(const char* name, const char** argv)
+{
+ if (!strcmp(name, "cd")) {
+ chdir(argv[0]);
+ sh_printerr();
+ return;
+ }
+
+ pid_t p;
+ if (!(p = fork())) {
+ if (execve(name, argv, NULL)) {
+ sh_printerr();
+ }
+ _exit(1);
+ }
+ setpgid(p, getpgid());
+ waitpid(p, NULL, 0);
+}
+
+void
+sh_loop()
+{
+ char buf[512];
+ char *cmd, *argpart;
+ signal(SIGINT, sigint_handle);
+
+ // set our shell as foreground process
+ // (unistd.h:tcsetpgrp is essentially a wrapper of this)
+ // stdout (by default, unless user did smth) is the tty we are currently at
+ ioctl(stdout, TIOCSPGRP, getpgid());
+
+ while (1) {
+ getcwd(pwd, 512);
+ printf("[\033[2m%s\033[39;49m]$ ", pwd);
+ size_t sz = read(stdin, buf, 511);
+ if (sz < 0) {
+ printf("fail to read user input (%d)\n", geterrno());
+ return;
+ }
+ buf[sz] = '\0';
+ parse_cmdline(buf, &cmd, &argpart);
+ if (cmd[0] == 0) {
+ printf("\n");
+ goto cont;
+ }
+ // cmd=="exit"
+ if (*(unsigned int*)cmd == 0x74697865U) {
+ break;
+ }
+ sh_exec(cmd, NULL);
+ cont:
+ printf("\n");
+ }
+}
+
+void
+main()
+{
+ printf("\n Simple shell. Use <PG_UP> or <PG_DOWN> to scroll.\n\n");
+ sh_loop();
+ _exit(0);
+}
\ No newline at end of file
--- /dev/null
+#include <signal.h>
+
+void
+sigchild_handler(int signum)
+{
+ printf("SIGCHLD received\n");
+}
+
+void
+sigsegv_handler(int signum)
+{
+ pid_t pid = getpid();
+ printf("SIGSEGV received on process %d\n", pid);
+ _exit(signum);
+}
+
+void
+sigalrm_handler(int signum)
+{
+ pid_t pid = getpid();
+ printf("I, pid %d, have received an alarm!\n", pid);
+}
+
+void
+main()
+{
+ signal(SIGCHLD, sigchild_handler);
+ signal(SIGSEGV, sigsegv_handler);
+ signal(SIGALRM, sigalrm_handler);
+
+ alarm(5);
+
+ int status;
+ pid_t p = 0;
+
+ printf("Child sleep 3s, parent pause.\n");
+ if (!fork()) {
+ sleep(3);
+ _exit(0);
+ }
+
+ pause();
+
+ printf("Parent resumed on SIGCHILD\n");
+
+ for (int i = 0; i < 5; i++) {
+ pid_t pid = 0;
+ if (!(pid = fork())) {
+ signal(SIGSEGV, sigsegv_handler);
+ sleep(i);
+ if (i == 3) {
+ i = *(int*)0xdeadc0de; // seg fault!
+ }
+ printf("%d\n", i);
+ _exit(0);
+ }
+ printf("Forked %d\n", pid);
+ }
+
+ while ((p = wait(&status)) >= 0) {
+ short code = WEXITSTATUS(status);
+ if (WIFSIGNALED(status)) {
+ printf("Process %d terminated by signal, exit_code: %d\n", p, code);
+ } else if (WIFEXITED(status)) {
+ printf("Process %d exited with code %d\n", p, code);
+ } else {
+ printf("Process %d aborted with code %d\n", p, code);
+ }
+ }
+
+ printf("done\n");
+}
\ No newline at end of file
char*
strcpy(char* dest, const char* src);
+int
+strcmp(const char* s1, const char* s2);
+
#endif /* __LUNAIX_STRING_H */
dest[i] = '\0';
return dest;
}
+
+int
+strcmp(const char* a, const char* b)
+{
+ while (*a && *a == *b) {
+ a++;
+ b++;
+ }
+ return *a - *b;
+}
\ No newline at end of file