📄 process.c
字号:
/* Copyright (C) 2005 David Decotigny This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <sos/assert.h>#include <sos/list.h>#include <sos/kmem_slab.h>#include <hwcore/irq.h>#include <drivers/bochs.h>#include <sos/umem_vmm.h>#include "process.h"#define SOS_PROCESS_MAX_OPENED_FILES 64#define SOS_PROCESS_MAX_NAMELEN 32/** * Definition of a process in SOS. A process is basically the * collection of all the resources requested by a user program. The * threads are one of these resources, the mm_context is one other * example of such resources. */struct sos_process{ char name[SOS_PROCESS_MAX_NAMELEN]; /** First important resource: the address space */ struct sos_umem_vmm_as *address_space; /** Second important resource: the CPU execution contexts, aka the threads executing in the context of this process. */ struct sos_thread *thread_list; sos_count_t nb_threads; /** Reference counter, including threads */ sos_count_t ref_cnt; /** The array of opened file descriptors */ struct sos_fs_opened_file * fds[SOS_PROCESS_MAX_OPENED_FILES]; /** Where the root of the process is (for chroot support). May be NULL */ struct sos_fs_opened_file * root; /** Where the current working dir of the process is */ struct sos_fs_opened_file * cwd; struct sos_process *prev, *next;};/** The list of processes in the system */static struct sos_process *process_list = NULL;/** The cache for the sos_process structures */struct sos_kslab_cache *cache_struct_process;/** * Helper function for debugging purposes */void sos_process_dumplist(){ struct sos_thread * cur_thr = sos_thread_get_current(); struct sos_process * proc; int nb_procs; sos_bochs_printf("<ps>\n"); list_foreach(process_list, proc, nb_procs) { struct sos_thread * thr; int nb_thrs; sos_bochs_printf(" proc@%p: '%s', %d threads, %d refs\n", proc, proc->name?proc->name:"(none)", proc->nb_threads, proc->ref_cnt); list_foreach_forward_named(proc->thread_list, thr, nb_thrs, prev_in_process, next_in_process) { if (thr == cur_thr) sos_bochs_printf(" thr@%p: [CURRENT]\n", thr); else sos_bochs_printf(" thr@%p: %cstate=%d eip=%p\n", thr, sos_cpu_context_is_in_user_mode(thr->cpu_state)?'u':'k', thr->state, (void*)sos_cpu_context_get_PC(thr->cpu_state)); } } sos_bochs_printf(" ======= %d processes =======\n", nb_procs); sos_bochs_printf("</ps>\n");}sos_ret_t sos_process_subsystem_setup(){ /* Create the cache for the process structures */ cache_struct_process = sos_kmem_cache_create("struct_process", sizeof(struct sos_process), 3, 0, SOS_KSLAB_CREATE_MAP | SOS_KSLAB_CREATE_ZERO); if (! cache_struct_process) return -SOS_ENOMEM; return SOS_OK;}struct sos_process *sos_process_create(const char *name, sos_bool_t do_copy_current_process){ sos_ret_t retval = SOS_OK; sos_ui32_t flags; struct sos_process *proc; proc = (struct sos_process*) sos_kmem_cache_alloc(cache_struct_process, 0); if (! proc) return NULL; /* proc is already filled with 0 (cache has SOS_KSLAB_CREATE_ZERO flag) */ /* Copy the file descriptors when needed */ if (do_copy_current_process) { struct sos_process * myself = sos_thread_get_current()->process; int fd; for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++) if (NULL != myself->fds[fd]) { retval = sos_fs_duplicate_opened_file(myself->fds[fd], proc, & proc->fds[fd]); if (SOS_OK != retval) goto end_create_proc; } retval = sos_fs_duplicate_opened_file(myself->root, proc, & proc->root); if (SOS_OK != retval) goto end_create_proc; retval = sos_fs_duplicate_opened_file(myself->cwd, proc, & proc->cwd); if (SOS_OK != retval) goto end_create_proc; } if (do_copy_current_process) proc->address_space = sos_umem_vmm_duplicate_current_thread_as(proc); else proc->address_space = sos_umem_vmm_create_empty_as(proc); if (NULL == proc->address_space) { /* Error */ retval = -SOS_ENOMEM; goto end_create_proc; } if (!name) { struct sos_thread * cur_thr = sos_thread_get_current(); if (do_copy_current_process) name = cur_thr->process->name; else name = "[UNNAMED]"; } strzcpy(proc->name, name, SOS_PROCESS_MAX_NAMELEN); /* Add it to the global list of processes */ sos_disable_IRQs(flags); list_add_tail(process_list, proc); sos_restore_IRQs(flags); /* Mark the process as referenced */ proc->ref_cnt = 1; end_create_proc: if (SOS_OK != retval) { int fd; /* Close the file descriptors */ for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++) if (NULL != proc->fds[fd]) sos_fs_close(proc->fds[fd]); if (proc->root) sos_fs_close(proc->root); if (proc->cwd) sos_fs_close(proc->cwd); sos_kmem_cache_free((sos_vaddr_t) proc); proc = NULL; } return proc;}inlinesos_ret_t sos_process_ref(struct sos_process *proc){ sos_ui32_t flags; sos_disable_IRQs(flags); proc->ref_cnt ++; sos_restore_IRQs(flags); return SOS_OK;}sos_count_t sos_process_get_nb_threads(const struct sos_process *proc){ sos_count_t retval; sos_ui32_t flags; sos_disable_IRQs(flags); retval = proc->nb_threads; sos_restore_IRQs(flags); return retval;}struct sos_mm_context *sos_process_get_mm_context(const struct sos_process *proc){ return sos_umem_vmm_get_mm_context(proc->address_space);}struct sos_umem_vmm_as *sos_process_get_address_space(const struct sos_process *proc){ return proc->address_space;}sos_ret_t sos_process_set_address_space(struct sos_process *proc, struct sos_umem_vmm_as *new_as){ int fd; /* Close the FD that are not allowed to be duplicated */ for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++) if ( (NULL != proc->fds[fd]) && (! (proc->fds[fd]->open_flags & SOS_FS_OPEN_KEEPONEXEC)) ) sos_fs_close(proc->fds[fd]); if (proc->address_space) { sos_ret_t retval = sos_umem_vmm_delete_as(proc->address_space); if (SOS_OK != retval) return retval; } proc->address_space = new_as; return SOS_OK;}struct sos_fs_opened_file *sos_process_get_root(const struct sos_process *proc){ return proc->root;}struct sos_fs_opened_file *sos_process_get_cwd(const struct sos_process *proc){ return proc->cwd;}struct sos_fs_opened_file *sos_process_get_opened_file(const struct sos_process *proc, int fd){ if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES)) return NULL; return proc->fds[fd];}sos_ret_tsos_process_chroot(struct sos_process *proc, struct sos_fs_opened_file * new_root, struct sos_fs_opened_file ** old_root){ *old_root = proc->root; proc->root = new_root; return SOS_OK;}sos_ret_tsos_process_chdir(struct sos_process *proc, struct sos_fs_opened_file * new_cwd, struct sos_fs_opened_file ** old_cwd){ *old_cwd = proc->cwd; proc->cwd = new_cwd; return SOS_OK;}sos_ret_tsos_process_register_opened_file(struct sos_process *proc, struct sos_fs_opened_file * of){ int i; for (i = 0 ; i < SOS_PROCESS_MAX_OPENED_FILES ; i++) if (NULL == proc->fds[i]) { proc->fds[i] = of; return i; } return -SOS_EMFILE;}sos_ret_tsos_process_unregister_opened_file(struct sos_process *proc, int fd){ if ((fd < 0) || (fd >= SOS_PROCESS_MAX_OPENED_FILES)) return -SOS_EBADF; proc->fds[fd] = NULL; return SOS_OK;}/* *************************************************** * Restricted functions */sos_ret_t sos_process_register_thread(struct sos_process *in_proc, struct sos_thread *thr){ sos_ui32_t flags; /* The process is assumed to be referenced by somebody */ SOS_ASSERT_FATAL(in_proc->ref_cnt > 0); /* Only threads that are being created are allowed to be attached to a process */ SOS_ASSERT_FATAL(thr->state == SOS_THR_CREATED); /* Update the list of the threads in the process */ thr->process = in_proc; /* Increment the reference count for the process */ sos_process_ref(in_proc); /* Add the thread to the process thread's list */ sos_disable_IRQs(flags); list_add_tail_named(in_proc->thread_list, thr, prev_in_process, next_in_process); in_proc->nb_threads ++; sos_restore_IRQs(flags); return SOS_OK;}/** The function responsible for releasing the resources held by the process. */sos_ret_t sos_process_unref(struct sos_process *proc){ sos_ui32_t flags; sos_ret_t retval; int fd; SOS_ASSERT_FATAL(proc->ref_cnt > 0); sos_disable_IRQs(flags); proc->ref_cnt --; if (proc->ref_cnt > 0) { sos_restore_IRQs(flags); return -SOS_EBUSY; } list_delete(process_list, proc); sos_restore_IRQs(flags); /* Close the file descriptors */ for (fd = 0 ; fd < SOS_PROCESS_MAX_OPENED_FILES ; fd++) if (NULL != proc->fds[fd]) sos_fs_close(proc->fds[fd]); sos_fs_close(proc->root); sos_fs_close(proc->cwd); /* First: free the user address space */ retval = sos_umem_vmm_delete_as(proc->address_space); SOS_ASSERT_FATAL(SOS_OK == retval); /* Free the process structure */ sos_kmem_cache_free((sos_vaddr_t)proc); return SOS_OK;}sos_ret_t sos_process_unregister_thread(struct sos_thread *thr){ sos_ui32_t flags; struct sos_process * in_proc = thr->process; SOS_ASSERT_FATAL(thr->state == SOS_THR_ZOMBIE); /* Update the list of the threads in the process */ thr->process = NULL; sos_disable_IRQs(flags); list_delete_named(in_proc->thread_list, thr, prev_in_process, next_in_process); SOS_ASSERT_FATAL(in_proc->nb_threads > 0); in_proc->nb_threads --; sos_restore_IRQs(flags); /* Unreference the process */ sos_process_unref(in_proc); return SOS_OK;}sos_ret_t sos_process_set_name(struct sos_process * proc, const char * new_name){ strzcpy(proc->name, new_name, SOS_PROCESS_MAX_NAMELEN); return SOS_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -