⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 process.c

📁 Simple Operating Systems (简称SOS)是一个可以运行在X86平台上(包括QEMU
💻 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 + -