Просмотр исходного кода

Kernel: Pass process arguments directly on the stack.

Get rid of the convoluted get_arguments and get_environment syscalls.
This patch also adds a simple /bin/env that just prints its environment.
Andreas Kling 6 лет назад
Родитель
Сommit
6d3e12899b
9 измененных файлов с 59 добавлено и 66 удалено
  1. 40 44
      Kernel/Process.cpp
  2. 0 4
      Kernel/Process.h
  3. 0 4
      Kernel/Syscall.cpp
  4. 0 2
      Kernel/Syscall.h
  5. 1 0
      Kernel/sync.sh
  6. 3 12
      LibC/entry.cpp
  7. 1 0
      Userland/.gitignore
  8. 5 0
      Userland/Makefile
  9. 9 0
      Userland/env.cpp

+ 40 - 44
Kernel/Process.cpp

@@ -223,9 +223,6 @@ Process* Process::fork(RegisterDump& regs)
     dbgprintf("fork: child=%p\n", child);
 #endif
 
-    child->m_initial_arguments = m_initial_arguments;
-    child->m_initial_environment = m_initial_environment;
-
     for (auto& region : m_regions) {
 #ifdef FORK_DEBUG
         dbgprintf("fork: cloning Region{%p} \"%s\" L%x\n", region.ptr(), region->name.characters(), region->laddr().get());
@@ -426,8 +423,46 @@ void Process::make_userspace_stack(Vector<String> arguments, Vector<String> envi
     m_stack_top3 = region->laddr().offset(default_userspace_stack_size).get();
     m_tss.esp = m_stack_top3;
 
-    m_initial_arguments = move(arguments);
-    m_initial_environment = move(environment);
+    char* stack_base = (char*)region->laddr().get();
+    int argc = arguments.size();
+    char** argv = (char**)stack_base;
+    char** env = argv + arguments.size() + 1;
+    char* bufptr = stack_base + (sizeof(char*) * (arguments.size() + 1)) + (sizeof(char*) * (environment.size() + 1));
+
+    size_t total_blob_size = 0;
+    for (auto& a : arguments)
+        total_blob_size += a.length() + 1;
+    for (auto& e : environment)
+        total_blob_size += e.length() + 1;
+
+    size_t total_meta_size = sizeof(char*) * (arguments.size() + 1) + sizeof(char*) * (environment.size() + 1);
+
+    // FIXME: It would be better if this didn't make us panic.
+    ASSERT((total_blob_size + total_meta_size) < default_userspace_stack_size);
+
+    for (size_t i = 0; i < arguments.size(); ++i) {
+        argv[i] = bufptr;
+        memcpy(bufptr, arguments[i].characters(), arguments[i].length());
+        bufptr += arguments[i].length();
+        *(bufptr++) = '\0';
+        printf("argv[%u] = %p (%s)\n", i, argv[i], argv[i]);
+    }
+    argv[arguments.size()] = nullptr;
+
+    for (size_t i = 0; i < environment.size(); ++i) {
+        env[i] = bufptr;
+        memcpy(bufptr, environment[i].characters(), environment[i].length());
+        bufptr += environment[i].length();
+        *(bufptr++) = '\0';
+        printf("env[%u] = %p (%s)\n", i, env[i], env[i]);
+    }
+    env[environment.size()] = nullptr;
+
+    // NOTE: The stack needs to be 16-byte aligned.
+    push_value_on_stack((dword)env);
+    push_value_on_stack((dword)argv);
+    push_value_on_stack((dword)argc);
+    push_value_on_stack(0);
 }
 
 int Process::exec(String path, Vector<String> arguments, Vector<String> environment)
@@ -529,45 +564,6 @@ Process* Process::create_user_process(const String& path, uid_t uid, gid_t gid,
     return process;
 }
 
-int Process::sys$get_environment(char*** environ)
-{
-    auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "environ");
-    if (!region)
-        return -ENOMEM;
-    MM.map_region(*this, *region);
-    char* envpage = (char*)region->laddr().get();
-    *environ = (char**)envpage;
-    char* bufptr = envpage + (sizeof(char*) * (m_initial_environment.size() + 1));
-    for (size_t i = 0; i < m_initial_environment.size(); ++i) {
-        (*environ)[i] = bufptr;
-        memcpy(bufptr, m_initial_environment[i].characters(), m_initial_environment[i].length());
-        bufptr += m_initial_environment[i].length();
-        *(bufptr++) = '\0';
-    }
-    (*environ)[m_initial_environment.size()] = nullptr;
-    return 0;
-}
-
-int Process::sys$get_arguments(int* argc, char*** argv)
-{
-    auto* region = allocate_region(LinearAddress(), PAGE_SIZE, "argv");
-    if (!region)
-        return -ENOMEM;
-    MM.map_region(*this, *region);
-    char* argpage = (char*)region->laddr().get();
-    *argc = m_initial_arguments.size();
-    *argv = (char**)argpage;
-    char* bufptr = argpage + (sizeof(char*) * (m_initial_arguments.size() + 1));
-    for (size_t i = 0; i < m_initial_arguments.size(); ++i) {
-        (*argv)[i] = bufptr;
-        memcpy(bufptr, m_initial_arguments[i].characters(), m_initial_arguments[i].length());
-        bufptr += m_initial_arguments[i].length();
-        *(bufptr++) = '\0';
-    }
-    (*argv)[m_initial_arguments.size()] = nullptr;
-    return 0;
-}
-
 Process* Process::create_kernel_process(String&& name, void (*e)())
 {
     auto* process = new Process(move(name), (uid_t)0, (gid_t)0, (pid_t)0, Ring0);

+ 0 - 4
Kernel/Process.h

@@ -183,8 +183,6 @@ public:
     int sys$usleep(useconds_t usec);
     int sys$gettimeofday(timeval*);
     int sys$gethostname(char* name, size_t length);
-    int sys$get_arguments(int* argc, char*** argv);
-    int sys$get_environment(char*** environ);
     int sys$uname(utsname*);
     int sys$readlink(const char*, char*, size_t);
     int sys$ttyname_r(int fd, char*, size_t);
@@ -386,8 +384,6 @@ private:
 
     static void notify_waiters(pid_t waitee, int exit_status, int signal);
 
-    Vector<String> m_initial_arguments;
-    Vector<String> m_initial_environment;
     HashTable<gid_t> m_gids;
 
     Region* m_signal_stack_user_region { nullptr };

+ 0 - 4
Kernel/Syscall.cpp

@@ -111,10 +111,6 @@ static dword handle(RegisterDump& regs, dword function, dword arg1, dword arg2,
         current->sys$exit((int)arg1);
         ASSERT_NOT_REACHED();
         return 0;
-    case Syscall::SC_get_arguments:
-        return current->sys$get_arguments((int*)arg1, (char***)arg2);
-    case Syscall::SC_get_environment:
-        return current->sys$get_environment((char***)arg1);
     case Syscall::SC_chdir:
         return current->sys$chdir((const char*)arg1);
     case Syscall::SC_uname:

+ 0 - 2
Kernel/Syscall.h

@@ -23,7 +23,6 @@
     __ENUMERATE_SYSCALL(getcwd) \
     __ENUMERATE_SYSCALL(gettimeofday) \
     __ENUMERATE_SYSCALL(gethostname) \
-    __ENUMERATE_SYSCALL(get_arguments) \
     __ENUMERATE_SYSCALL(chdir) \
     __ENUMERATE_SYSCALL(uname) \
     __ENUMERATE_SYSCALL(set_mmap_name) \
@@ -31,7 +30,6 @@
     __ENUMERATE_SYSCALL(write) \
     __ENUMERATE_SYSCALL(ttyname_r) \
     __ENUMERATE_SYSCALL(stat) \
-    __ENUMERATE_SYSCALL(get_environment) \
     __ENUMERATE_SYSCALL(getsid) \
     __ENUMERATE_SYSCALL(setsid) \
     __ENUMERATE_SYSCALL(getpgid) \

+ 1 - 0
Kernel/sync.sh

@@ -69,6 +69,7 @@ cp -v ../Userland/top mnt/bin/top
 cp -v ../Userland/ln mnt/bin/ln
 cp -v ../Userland/df mnt/bin/df
 cp -v ../Userland/su mnt/bin/su
+cp -v ../Userland/env mnt/bin/env
 chmod 4755 mnt/bin/su
 cp -v ../Applications/Terminal/Terminal mnt/bin/Terminal
 cp -v ../Applications/FontEditor/FontEditor mnt/bin/FontEditor

+ 3 - 12
LibC/entry.cpp

@@ -13,28 +13,19 @@ char** environ;
 void __malloc_init();
 void __stdio_init();
 
-int _start()
+int _start(int argc, char** argv, char** env)
 {
     errno = 0;
+    environ = env;
 
     __stdio_init();
     __malloc_init();
 
-    int status = 254;
-    int argc;
-    char** argv;
-    int rc = syscall(SC_get_arguments, &argc, &argv);
-    if (rc < 0)
-        goto epilogue;
-    rc = syscall(SC_get_environment, &environ);
-    if (rc < 0)
-        goto epilogue;
-    status = main(argc, argv);
+    int status = main(argc, argv);
 
     fflush(stdout);
     fflush(stderr);
 
-epilogue:
     syscall(SC_exit, status);
 
     // Birger's birthday <3

+ 1 - 0
Userland/.gitignore

@@ -34,3 +34,4 @@ pape
 ln
 df
 su
+env

+ 5 - 0
Userland/Makefile

@@ -30,6 +30,7 @@ OBJS = \
        df.o \
        ln.o \
        su.o \
+       env.o \
        rm.o
 
 APPS = \
@@ -65,6 +66,7 @@ APPS = \
        ln \
        df \
        su \
+       env \
        rm
 
 ARCH_FLAGS =
@@ -184,6 +186,9 @@ df: df.o
 su: su.o
 	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
 
+env: env.o
+	$(LD) -o $@ $(LDFLAGS) $< ../LibC/LibC.a
+
 .cpp.o:
 	@echo "CXX $<"; $(CXX) $(CXXFLAGS) -o $@ -c $<
 

+ 9 - 0
Userland/env.cpp

@@ -0,0 +1,9 @@
+#include <unistd.h>
+#include <stdio.h>
+
+int main(int, char**)
+{
+    for (size_t i = 0; environ[i]; ++i)
+        printf("%s\n", environ[i]);
+    return 0;
+}