bash源代码分析----子进程执行完make_child函数中的fork函数,然后执行shell_execve函数

子进程执行完make_child函数中的fork函数,然后执行shell_execve函数

而父进程执行到wait_for函数等待子进程返回。

关键的一部分内容啊。

子进程需要在shell_execve函数处下断点。

至此,我们有几个关键的断点。

第一个,rl_newline函数,输入ls命令回车后会停到rl_newline函数处。

第二个,父进程执行到wait_for函数处等待。

第三个,子进程执行到shell_execve函数处开始执行ls命令。

/* Call execve (), handling interpreting shell scripts, and handling
   exec failures. */
int
shell_execve (command, args, env)
     char *command;
     char **args, **env;
{
  int larray, i, fd;
  char sample[80];
  int sample_len;

  SETOSTYPE (0);        /* Some systems use for USG/POSIX semantics */
  execve (command, args, env);
  i = errno;            /* error from execve() */
  CHECK_TERMSIG;
  SETOSTYPE (1);

  /* If we get to this point, then start checking out the file.
     Maybe it is something we can hack ourselves. */
  if (i != ENOEXEC)
    {
      if (file_isdir (command))
#if defined (EISDIR)
    internal_error (_("%s: %s"), command, strerror (EISDIR));
#else
    internal_error (_("%s: is a directory"), command);
#endif
      else if (executable_file (command) == 0)
    {
      errno = i;
      file_error (command);
    }
      /* errors not involving the path argument to execve. */
      else if (i == E2BIG || i == ENOMEM)
    {
      errno = i;
      file_error (command);
    }
      else
    {
      /* The file has the execute bits set, but the kernel refuses to
         run it for some reason.  See why. */
#if defined (HAVE_HASH_BANG_EXEC)
      READ_SAMPLE_BUF (command, sample, sample_len);
      if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
        {
          char *interp;
          int ilen;

          interp = getinterp (sample, sample_len, (int *)NULL);
          ilen = strlen (interp);
          errno = i;
          if (interp[ilen - 1] == '\r')
        {
          interp = xrealloc (interp, ilen + 2);
          interp[ilen - 1] = '^';
          interp[ilen] = 'M';
          interp[ilen + 1] = '\0';
        }
          sys_error (_("%s: %s: bad interpreter"), command, interp ? interp : "");
          FREE (interp);
          return (EX_NOEXEC);
        }
#endif
      errno = i;
      file_error (command);
    }
      return ((i == ENOENT) ? EX_NOTFOUND : EX_NOEXEC);    /* XXX Posix.2 says that exit status is 126 */
    }

  /* This file is executable.
     If it begins with #!, then help out people with losing operating
     systems.  Otherwise, check to see if it is a binary file by seeing
     if the contents of the first line (or up to 80 characters) are in the
     ASCII set.  If it's a text file, execute the contents as shell commands,
     otherwise return 126 (EX_BINARY_FILE). */
  READ_SAMPLE_BUF (command, sample, sample_len);

  if (sample_len == 0)
    return (EXECUTION_SUCCESS);

  /* Is this supposed to be an executable script?
     If so, the format of the line is "#! interpreter [argument]".
     A single argument is allowed.  The BSD kernel restricts
     the length of the entire line to 32 characters (32 bytes
     being the size of the BSD exec header), but we allow 80
     characters. */
  if (sample_len > 0)
    {
#if !defined (HAVE_HASH_BANG_EXEC)
      if (sample_len > 2 && sample[0] == '#' && sample[1] == '!')
    return (execute_shell_script (sample, sample_len, command, args, env));
      else
#endif
      if (check_binary_file (sample, sample_len))
    {
      internal_error (_("%s: cannot execute binary file"), command);
      return (EX_BINARY_FILE);
    }
    }

  /* We have committed to attempting to execute the contents of this file
     as shell commands. */

  initialize_subshell ();

  set_sigint_handler ();

  /* Insert the name of this shell into the argument list. */
  larray = strvec_len (args) + 1;
  args = strvec_resize (args, larray + 1);

  for (i = larray - 1; i; i--)
    args[i] = args[i - 1];

  args[0] = shell_name;
  args[1] = command;
  args[larray] = (char *)NULL;

  if (args[0][0] == '-')
    args[0]++;

#if defined (RESTRICTED_SHELL)
  if (restricted)
    change_flag ('r', FLAG_OFF);
#endif

  if (subshell_argv)
    {
      /* Can't free subshell_argv[0]; that is shell_name. */
      for (i = 1; i < subshell_argc; i++)
    free (subshell_argv[i]);
      free (subshell_argv);
    }

  dispose_command (currently_executing_command);    /* XXX */
  currently_executing_command = (COMMAND *)NULL;

  subshell_argc = larray;
  subshell_argv = args;
  subshell_envp = env;

  unbind_args ();    /* remove the positional parameters */

  longjmp (subshell_top_level, 1);
  /*NOTREACHED*/
}

 

 


(gdb) n
execute_disk_command (cmdflags=0, fds_to_close=0xaae3c8, async=0, pipe_out=-1, pipe_in=-1,
    command_line=0xaae2e8 "ls --color=auto", redirects=0x0, words=<optimized out>) at execute_cmd.c:4685
4685      if (pid == 0)
(gdb) b shell_execve
Breakpoint 1 at 0x42f8f0: file execute_cmd.c, line 4957.
(gdb) c
Continuing.

Breakpoint 1, shell_execve (command=command@entry=0xaad3a8 "/usr/bin/ls", args=0xab9d08, env=0x8f5008)
    at execute_cmd.c:4957
4957    {
(gdb) s
4963      execve (command, args, env);
(gdb) bt
#0  shell_execve (command=command@entry=0xaad3a8 "/usr/bin/ls", args=0xab9d08, env=0x8f5008) at execute_cmd.c:4963
#1  0x0000000000430f8a in execute_disk_command (cmdflags=0, fds_to_close=0xaae3c8, async=0, pipe_out=-1, pipe_in=-1,
    command_line=0xaae2e8 "ls --color=auto", redirects=0x0, words=<optimized out>) at execute_cmd.c:4762
#2  execute_simple_command (simple_command=<optimized out>, pipe_in=pipe_in@entry=-1, pipe_out=pipe_out@entry=-1,
    async=async@entry=0, fds_to_close=fds_to_close@entry=0xaae3c8) at execute_cmd.c:3990
#3  0x0000000000431e9e in execute_command_internal (command=0xa98808, asynchronous=0, pipe_in=-1, pipe_out=-1,
    fds_to_close=0xaae3c8) at execute_cmd.c:735
#4  0x000000000043342e in execute_command (command=0xa98808) at execute_cmd.c:382
#5  0x000000000041e253 in reader_loop () at eval.c:152
#6  0x000000000041c88e in main (argc=1, argv=0x7fffffffe2a8, env=0x7fffffffe2b8) at shell.c:749
(gdb)

上一篇:(译)利用ASP.NET加密和解密Web.config中连接字符串


下一篇:「SequoiaDB巨杉数据库」createCL()