From: Cristiano Giuffrida Date: Wed, 23 Dec 2009 14:05:20 +0000 (+0000) Subject: Share exec images in RS. X-Git-Tag: v3.1.6~136 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/CHANGES?a=commitdiff_plain;h=6f912993ff74ac6a62de11555e5b4dac98081ba4;p=minix.git Share exec images in RS. RS CHANGES: - RS retains information on both labels and process names now. Labels for boot processes are configured in the boot image priv table. Process names are inherited from the in-kernel boot image table. - When RS_REUSE is specified in do_up, RS looks for an existing slot having the same process name as the one we are about to start. If one is found with an in-memory copy of its executable image, the image is then shared between the two processes, rather than copying it again. This behavior can be specified by using 'service -r' when starting a system service from the command line. --- diff --git a/drivers/memory/ramdisk/rc b/drivers/memory/ramdisk/rc index 4ef68b53c..a03e4a914 100644 --- a/drivers/memory/ramdisk/rc +++ b/drivers/memory/ramdisk/rc @@ -13,7 +13,7 @@ then /bin/service -c up /bin/bios_wini -dev /dev/c0d0 else /bin/service -c up /bin/at_wini -dev /dev/c0d0 -config /etc/system.conf -label at_wini_0 - /bin/service -c up /bin/at_wini -dev /dev/c1d0 -config /etc/system.conf -label at_wini_1 -args ata_instance=1 + /bin/service -c -r up /bin/at_wini -dev /dev/c1d0 -config /etc/system.conf -label at_wini_1 -args ata_instance=1 fi rootdev=`sysenv rootdev` || echo 'No rootdev?' diff --git a/servers/rs/main.c b/servers/rs/main.c index 2b3a0a460..2986dc169 100644 --- a/servers/rs/main.c +++ b/servers/rs/main.c @@ -453,6 +453,9 @@ PRIVATE void init_server(void) * service by using vm_set_priv(). We need a more uniform privilege * management scheme in VM for this change. */ + /* Get label. */ + strcpy(rp->r_label, boot_image_priv->label); + /* Force a static privilege id for system services in the boot image. */ rp->r_priv.s_id = static_priv_id(_ENDPOINT_P(boot_image_priv->endpoint)); @@ -489,8 +492,8 @@ PRIVATE void init_server(void) rp->r_dev_style = boot_image_dev->dev_style; /* device style */ rp->r_period = boot_image_dev->period; /* heartbeat period */ - /* Get label. */ - strcpy(rp->r_label, ip->proc_name); + /* Get process name. */ + strcpy(rp->r_proc_name, ip->proc_name); /* Get command settings. */ rp->r_cmd[0]= '\0'; diff --git a/servers/rs/manager.c b/servers/rs/manager.c index 0fc66b166..053d13777 100644 --- a/servers/rs/manager.c +++ b/servers/rs/manager.c @@ -29,8 +29,9 @@ FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags, FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) ); FORWARD _PROTOTYPE( int fork_nb, (void) ); FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) ); -FORWARD _PROTOTYPE( int copy_exec, (struct rproc *rp_src, +FORWARD _PROTOTYPE( int share_exec, (struct rproc *rp_src, struct rproc *rp_dst) ); +FORWARD _PROTOTYPE( void free_slot, (struct rproc *rp) ); FORWARD _PROTOTYPE( void run_script, (struct rproc *rp) ); FORWARD _PROTOTYPE( char *get_next_label, (char *ptr, char *label, char *caller_label) ); @@ -128,8 +129,6 @@ size_t dst_len; dst_label[len] = 0; - if (rs_verbose) - printf("RS: copy_label: using label (custom) '%s'\n", dst_label); return OK; } @@ -203,6 +202,21 @@ message *m_ptr; /* request message pointer */ } rp->r_argv[arg_count] = NULL; /* end with NULL pointer */ rp->r_argc = arg_count; + + /* Process name for the service. */ + cmd_ptr = strrchr(rp->r_argv[0], '/'); + if (cmd_ptr) + cmd_ptr++; + else + cmd_ptr= rp->r_argv[0]; + len= strlen(cmd_ptr); + if (len > P_NAME_LEN-1) + len= P_NAME_LEN-1; /* truncate name */ + memcpy(rp->r_proc_name, cmd_ptr, len); + rp->r_proc_name[len]= '\0'; + if(rs_verbose) + printf("RS: do_up: using proc_name (from binary %s) '%s'\n", + rp->r_argv[0], rp->r_proc_name); if(rs_start.rss_label.l_len > 0) { /* RS_UP caller has supplied a custom label for this service. */ @@ -214,19 +228,15 @@ message *m_ptr; /* request message pointer */ printf("RS: do_up: using label (custom) '%s'\n", rp->r_label); } else { /* Default label for the service. */ - label= strrchr(rp->r_argv[0], '/'); - if (label) - label++; - else - label= rp->r_argv[0]; + label = rp->r_proc_name; len= strlen(label); if (len > MAX_LABEL_LEN-1) len= MAX_LABEL_LEN-1; /* truncate name */ memcpy(rp->r_label, label, len); rp->r_label[len]= '\0'; if(rs_verbose) - printf("RS: do_up: using label (from binary %s) '%s'\n", - rp->r_argv[0], rp->r_label); + printf("RS: do_up: using label (from proc_name) '%s'\n", + rp->r_label); } if(rs_start.rss_nr_control > 0) { @@ -302,12 +312,11 @@ message *m_ptr; /* request message pointer */ exst_cpy = 0; if(rs_start.rss_flags & RF_REUSE) { - char *cmd = rp->r_cmd; int i; - + for(i = 0; i < NR_SYS_PROCS; i++) { rp2 = &rproc[i]; - if(strcmp(rp->r_cmd, rp2->r_cmd) == 0 && + if(strcmp(rp->r_proc_name, rp2->r_proc_name) == 0 && (rp2->r_sys_flags & SF_USE_COPY)) { /* We have found the same binary that's * already been copied */ @@ -320,7 +329,7 @@ message *m_ptr; /* request message pointer */ if(!exst_cpy) s = read_exec(rp); else - s = copy_exec(rp, rp2); + s = share_exec(rp, rp2); if (s != OK) return s; @@ -463,15 +472,8 @@ PUBLIC int do_down(message *m_ptr) stop_service(rp,RS_EXITING); if (rp->r_pid == -1) { - /* Process is already gone */ - rp->r_flags = 0; /* release slot */ - if (rp->r_exec) - { - free(rp->r_exec); - rp->r_exec= NULL; - } - proc = _ENDPOINT_P(rp->r_proc_nr_e); - rproc_ptr[proc] = NULL; + /* Process is already gone, release slot. */ + free_slot(rp); return(OK); } @@ -860,12 +862,7 @@ PUBLIC void do_exit(message *m_ptr) } /* Release slot. */ - rp->r_flags = 0; - if (rp->r_exec) - { - free(rp->r_exec); - rp->r_exec= NULL; - } + free_slot(rp); } else if(rp->r_flags & RS_REFRESHING) { short is_updating = rp->r_flags & RS_UPDATING; @@ -1268,6 +1265,9 @@ message *m_ptr; return(OK); } +/*===========================================================================* + * fork_nb * + *===========================================================================*/ PRIVATE pid_t fork_nb() { message m; @@ -1275,65 +1275,109 @@ PRIVATE pid_t fork_nb() return(_syscall(PM_PROC_NR, FORK_NB, &m)); } -PRIVATE int copy_exec(rp_dst, rp_src) +/*===========================================================================* + * share_exec * + *===========================================================================*/ +PRIVATE int share_exec(rp_dst, rp_src) struct rproc *rp_dst, *rp_src; { - /* Copy binary from rp_src to rp_dst. */ - rp_dst->r_exec_len = rp_src->r_exec_len; - rp_dst->r_exec = malloc(rp_dst->r_exec_len); - if(rp_dst->r_exec == NULL) - return ENOMEM; - - memcpy(rp_dst->r_exec, rp_src->r_exec, rp_dst->r_exec_len); - if(rp_dst->r_exec_len != 0 && rp_dst->r_exec != NULL) - return OK; - - rp_dst->r_exec = NULL; - return EIO; + if(rs_verbose) { + printf("RS: share_exec: sharing exec image from %s to %s\n", + rp_src->r_label, rp_dst->r_label); + } + + /* Share exec image from rp_src to rp_dst. */ + rp_dst->r_exec_len = rp_src->r_exec_len; + rp_dst->r_exec = rp_src->r_exec; + + return OK; } +/*===========================================================================* + * read_exec * + *===========================================================================*/ PRIVATE int read_exec(rp) struct rproc *rp; { - int e, r, fd; - char *e_name; - struct stat sb; + int e, r, fd; + char *e_name; + struct stat sb; + + e_name= rp->r_argv[0]; + if(rs_verbose) { + printf("RS: read_exec: copying exec image from: %s\n", e_name); + } + r= stat(e_name, &sb); + if (r != 0) + return -errno; - e_name= rp->r_argv[0]; - r= stat(e_name, &sb); - if (r != 0) - return -errno; + fd= open(e_name, O_RDONLY); + if (fd == -1) + return -errno; - fd= open(e_name, O_RDONLY); - if (fd == -1) - return -errno; + rp->r_exec_len= sb.st_size; + rp->r_exec= malloc(rp->r_exec_len); + if (rp->r_exec == NULL) + { + printf("RS: read_exec: unable to allocate %d bytes\n", + rp->r_exec_len); + close(fd); + return ENOMEM; + } - rp->r_exec_len= sb.st_size; - rp->r_exec= malloc(rp->r_exec_len); - if (rp->r_exec == NULL) - { - printf("RS: read_exec: unable to allocate %d bytes\n", - rp->r_exec_len); - close(fd); - return ENOMEM; - } + r= read(fd, rp->r_exec, rp->r_exec_len); + e= errno; + close(fd); + if (r == rp->r_exec_len) + return OK; - r= read(fd, rp->r_exec, rp->r_exec_len); - e= errno; - close(fd); - if (r == rp->r_exec_len) - return OK; + printf("RS: read_exec: read failed %d, errno %d\n", r, e); - printf("RS: read_exec: read failed %d, errno %d\n", r, e); + free(rp->r_exec); + rp->r_exec= NULL; - free(rp->r_exec); - rp->r_exec= NULL; + if (r >= 0) + return EIO; + else + return -e; +} - if (r >= 0) - return EIO; - else - return -e; +/*===========================================================================* + * free_slot * + *===========================================================================*/ +PRIVATE void free_slot(rp) +struct rproc *rp; +{ + int slot_nr, has_shared_exec; + struct rproc *other_rp; + + /* Free memory if necessary. */ + if(rp->r_sys_flags & SF_USE_COPY) { + /* Search for some other slot sharing the same exec image. */ + has_shared_exec = FALSE; + for (slot_nr = 0; slot_nr < NR_SYS_PROCS; slot_nr++) { + other_rp = &rproc[slot_nr]; /* get pointer to slot */ + if (other_rp->r_flags & RS_IN_USE && other_rp != rp + && other_rp->r_exec == rp->r_exec) { /* found! */ + has_shared_exec = TRUE; + } + } + + /* If nobody uses our copy of the exec image, we can get rid of it. */ + if(!has_shared_exec) { + if(rs_verbose) { + printf("RS: free_slot: free exec image from %s\n", rp->r_label); + } + free(rp->r_exec); + rp->r_exec = NULL; + rp->r_exec_len = 0; + } + } + + /* Mark slot as no longer in use.. */ + rp->r_flags = 0; + rproc_ptr[_ENDPOINT_P(rp->r_proc_nr_e)] = NULL; } /*===========================================================================* diff --git a/servers/rs/table.c b/servers/rs/table.c index 4ed3d1a9c..eca1a98bb 100644 --- a/servers/rs/table.c +++ b/servers/rs/table.c @@ -35,23 +35,23 @@ PRIVATE int /* Definition of the boot image priv table. */ PUBLIC struct boot_image_priv boot_image_priv_table[] = { - /*endpoint, priv flags, traps, ipcto, kcalls */ - { VM_PROC_NR, VM_F, SRV_T, SRV_M, vm_kc }, - { PM_PROC_NR, SRV_F, SRV_T, SRV_M, pm_kc }, - { FS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc }, - { DS_PROC_NR, SRV_F, SRV_T, SRV_M, ds_kc }, - { TTY_PROC_NR, SRV_F, SRV_T, SRV_M, tty_kc }, - { MEM_PROC_NR, SRV_F, SRV_T, SRV_M, mem_kc }, - { LOG_PROC_NR, SRV_F, SRV_T, SRV_M, drv_kc }, - { MFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc }, - { PFS_PROC_NR, SRV_F, SRV_T, SRV_M, fs_kc }, - { INIT_PROC_NR, RUSR_F, RUSR_T, RUSR_M, rusr_kc }, - { NULL_BOOT_NR, 0, 0, 0, no_kc } /* null entry */ + /*endpoint, label, flags, traps, ipcto, kcalls */ + { VM_PROC_NR, "vm", VM_F, SRV_T, SRV_M, vm_kc }, + { PM_PROC_NR, "pm", SRV_F, SRV_T, SRV_M, pm_kc }, + { FS_PROC_NR, "vfs", SRV_F, SRV_T, SRV_M, fs_kc }, + { DS_PROC_NR, "ds", SRV_F, SRV_T, SRV_M, ds_kc }, + { TTY_PROC_NR, "tty", SRV_F, SRV_T, SRV_M, tty_kc }, + { MEM_PROC_NR, "memory", SRV_F, SRV_T, SRV_M, mem_kc }, + { LOG_PROC_NR, "log", SRV_F, SRV_T, SRV_M, drv_kc }, + { MFS_PROC_NR, "fs_imgrd", SRV_F, SRV_T, SRV_M, fs_kc }, + { PFS_PROC_NR, "pfs", SRV_F, SRV_T, SRV_M, fs_kc }, + { INIT_PROC_NR, "init", RUSR_F, RUSR_T, RUSR_M, rusr_kc }, + { NULL_BOOT_NR, "", 0, 0, 0, no_kc } /* null entry */ }; /* Definition of the boot image sys table. */ PUBLIC struct boot_image_sys boot_image_sys_table[] = { - /*endpoint, sys flags */ + /*endpoint, flags */ { LOG_PROC_NR, SRVC_SF }, { MFS_PROC_NR, SRVC_SF }, { PFS_PROC_NR, SRVC_SF }, diff --git a/servers/rs/type.h b/servers/rs/type.h index 473bd511b..aebd82224 100644 --- a/servers/rs/type.h +++ b/servers/rs/type.h @@ -6,6 +6,7 @@ /* Definition of an entry of the boot image priv table. */ struct boot_image_priv { endpoint_t endpoint; /* process endpoint number */ + char label[MAX_LABEL_LEN]; /* label to assign to this service */ int flags; /* privilege flags */ short trap_mask; /* allowed system call traps */ @@ -50,7 +51,8 @@ struct rproc { char *r_exec; /* Executable image */ size_t r_exec_len; /* Length of image */ - char r_label[MAX_LABEL_LEN]; /* unique name of this service */ + char r_label[MAX_LABEL_LEN]; /* label of this service */ + char r_proc_name[P_NAME_LEN]; /* process name of this service */ char r_cmd[MAX_COMMAND_LEN]; /* raw command plus arguments */ char r_script[MAX_SCRIPT_LEN]; /* name of the restart script executable */ char *r_argv[MAX_NR_ARGS+2]; /* parsed arguments vector */