关闭

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

标签: c语言linux
221人阅读 评论(0) 收藏 举报
分类:

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


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


#PS:这个只是  《  我自己    》理解,如果和你的原则相冲突,请


谅解,勿喷 


近段时间看一些代码,自己也写了一些。但是写着写着感觉自己迷茫了,自己对程序的结构越来越模糊,甚至都不相信自己的写的部分,或者相信自己的知识。


那么现在就来终结这些想法,让自己提升一下。

本系列文章主要分为两部分,(一)是分析程序在内存中的分布(二)是linux下程序的执行流程


下面是linux下程序的执行流程:

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


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


当你在shell中输入

<span style="white-space:pre">	</span>./XXXXX
这个时候,一个程序就开始执行了。现在就进入我们这篇文章要讲的重点。(一个程序要可以执行的前戏就是之前的分析)


现在我要开始执行XXXXX程序:

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


第一步:

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


第二步:

下面来分析execve()函数的执行过程。

查看man手册:

execve源码:


在调用INLINE_SYSCALL宏后,



调用INTERNAL_SYSCALL()


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

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

  1. asmlinkage int sys_execve(struct pt_regs regs)  
  2. {  
  3.     int error;  
  4.     char * filename;  
  5.   
  6.     filename = getname((char *) regs.ebx);
  7.     error = PTR_ERR(filename);  
  8.     if (IS_ERR(filename))  
  9.         goto out;  
  10.     error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, &regs);  
  11.     if (error == 0)  
  12.         current->ptrace &= ~PT_DTRACE;  
  13.     putname(filename);  
  14. out:  
  15.     return error;  
  16. }  
调用do_execve(),先收集信息,调用search_binary_handler()函数,根据可执行文件类型,调用不同的的处理函数去执行。(后面详细的信息可以去阅读源码,这里就不一一说明)

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


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


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


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


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


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:40911次
    • 积分:836
    • 等级:
    • 排名:千里之外
    • 原创:39篇
    • 转载:6篇
    • 译文:1篇
    • 评论:20条
    最新评论