C程序问题归纳(static,auto,register,extern,程序内存分布图,linux下程序的执行过程......)(二)

PS:要转载请注明出处,本人版权所有。

PS: 这个只是基于《我自己》的理解,

如果和你的原则及想法相冲突,请谅解,勿喷。

前置说明

  本文作为本人csdn blog的主站的备份。(BlogID=019)
  本文发布于 2016-06-02 14:35:06,现用MarkDown+图床做备份更新。blog原图已丢失,使用csdn所存的图进行更新。(BlogID=019)

环境说明

  无

前言


  近段时间看一些代码,自己也写了一些。但是写着写着感觉自己迷茫了,自己对程序的结构越来越模糊,甚至都不相信自己的写的部分,或者相信自己的知识。那么现在就来终结这些想法,让自己提升一下。本系列文章主要分为两部分,(一)是分析程序在内存中的分布(二)是linux下程序的执行流程





linux下程序的执行流程


  对Linux有了解的人都应该知道,在系统中只有一个pid为1的父进程(init),其他的进程都是这个进程衍生出来的子进程(fork),从而形成了以init为树根的一颗树。如图:

rep_img

  如果你有图形桌面,则会在初始化好了开机启动服务后,会调用图形桌面启动器lightdm,然后图形界面初始化,然后你双击鼠标运行的程序就会是图形桌面的子进程。而我们在shell下运行的程序就会是在lightdm->/usr/bin/x-term(以上图为例)下形成子进程。

  当你在shell中输入

./XXXXX

这个时候,一个程序就开始执行了。现在就进入我们这篇文章要讲的重点。(一个程序要可以执行的前戏就是之前的分析)



现在我要开始执行XXXXX程序

  在shell中输入上图命令,并回车后。

  • 第一步:shell 会fork 出一个子进程。同时wait()子进程结束。如果在shell命令后加入&等符号,表示后台执行时,shell fork后,不会wait()子进程,而直接返回。新fork()出的子进程,将会调用一个用户态函数execve() 加载xxxxx程序的文件。(放在磁盘上的静态数据)

  • 第二步:下面来分析execve()函数的执行过程。查看man手册:

rep_img

execve源码:

rep_img

在调用INLINE_SYSCALL宏后,

rep_img

调用INTERNAL_SYSCALL()

rep_img

(提示:其实以上部分就是熟知的GLIBC怎么实现用户API与系统调用结合的过程)

保存系统调用号,然后保存到寄存器,然后切换到内核态,根据调用号查询到sys_execve(),执行sys_execve()

asmlinkage int sys_execve(struct pt_regs regs)  
{  
    int error;  
    char * filename;  
  
    filename = getname((char *) regs.ebx);
    error = PTR_ERR(filename);  
    if (IS_ERR(filename))  
        goto out;  
    error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);  
    if (error == 0)  
        current->ptrace &= ~PT_DTRACE;  
    putname(filename);  
out:  
    return error;  
}  

调用do_execve(),先收集信息,调用search_binary_handler()函数,根据可执行文件类型,调用不同的的处理函数去执行。(后面详细的信息可以去阅读源码,这里就不一一说明)

(由于本人水平有限,后面部分只知道个大概,就不献丑了)

这样一个程序就执行起来了。是不是非常的简单。





后记


  无

参考文献




打赏、订阅、收藏、丢香蕉、硬币,请关注公众号(攻城狮的搬砖之路)
qrc_img

PS: 请尊重原创,不喜勿喷。

PS: 要转载请注明出处,本人版权所有。

PS: 有问题请留言,看到后我会第一时间回复。

posted on 2023-02-11 16:16  SkyOnSky  阅读(30)  评论(0)    收藏  举报

导航