标签:ext 定位 信息 question 共存 bsh for 视频 代码
能用图说明的问题,就少用文字描述:
ELF可执行文件中有三种主要的目标文件:
sillysen@20179209:~/homework$ readelf -h main
c查看一个main目标文件的信息:int main(int argc,char *argv[]){
int pid;
pid = fork();
if(pid < 0){
fprintf(stderr,"Fork failed!");
exit(-1);
}
else{
execlp("/home/sillysen/homework/11.14/main","./main","2","0","1","7","9","2","0","9",NULL);
exit(0);
}
return 0;
}
运行结果如下:
execlp函数的第一个参数是可执行程序的路径,后面的参数是这个可执行程序运行时的参数,值得注意的是命令本身也算一个参数,所以第二个参数一般就是命令本身。至于这里为什么输出两遍,而且是这样的格式,我也不太清楚,欢迎大家指正。
我们测试的代码非常简单,能说明问题就行。把sharelib.c制作成动态库,然后在main函数中调用。源代码如下:
/*
main 函数
*/
#include <stdio.h>
extern int print();
int main(int argc, char *argv[]){
print();
return 0;
}
/*
sharelib
*/
int print(){
printf("This is share lib!\n");
return 0;
}
sillysen@20179209:~/homework/11.16$ gcc -fPIC -shared -o libsharelib.so sharelib.c //制作动态库libsharelib.so
sillysen@20179209:~/homework/11.16$ sudo cp libsharelib.so /usr/lib //将生成的动态库拷贝到/usr/lib目录,只有这样生成的程序才能执行
修改main函数为如下:
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
int main(int argc, char *argv[]){
//print();
void * handle = dlopen("libsharelib.so",RTLD_NOW);
if(handle == NULL){
printf("Open Lib libsharelib.so Error:%s\n",dlerror);
return -1;
}
int (*func)(void);
char * error;
func = dlsym(handle,"print");
if((error = dlerror()) != NULL){
printf("print not found:%s\n",error);
return -1;
}
func();
dlclose(handle);
return 0;
}
编译命令为sillysen@20179209:~/homework/11.16$ gcc -o main main.c -ldl
,使用dl系列函数除了要在头文件中包含dlfcn.h之外,在编译链接时还得加-ldl参数。
根据孟老师视频中讲解的execve系统调用的整个过程,可以把其中一些重要的函数摘录出来,画出如下的一个简易的流程图(不完整的流程图,只包含老师讲解过的过程)如下:
为此我在关键位置设置断点(除了视频中讲解的三个外,又加了其他几个):
开始GDB跟踪:
分析:
return do_execve(getname(filename),argv,envp);
时候我没有s进去看;而load_elf_interp断点没有出现是因为这里调用的fork为静态装载可执行程序,而只有动态装载才会调用这个函数,到此还有两个断点do_execve_common和exec_binprm没有出现。为此我还特意断了一下exec_binprm中search_binary_handler函数,gdb显示没有这个符号,这里就留下一个问题,为什么会出现这样的情况?根据视频中讲解这个函数的目的是装载bprm数据结构,但gdb跟踪过程中却没有这一步。。。虚拟文件系统,作为内核子系统,为用户程序提供了文件和文件系统相关的接口。系统中所有文件系统不但依赖VFS共存,而且也依靠VFS系统协同工作。通过虚拟文件系统,程序可以利用标准的Uinx系统调用对不同文件系统,甚至不同介质上的文件系统进行读写操作。总而言之,linux下一切皆文件!
之所以可以使用这种通用接口对所有类型的文件系统进行操作,是因为内核在它的底层文件系统接口上建立了一个抽象层。该抽象层使Linux能够支持各种文件系统,即便是它们在功能和行为上存在很大的差别,为了支持多文件系统,VFS提供了一个通用文件系统模型,该模型囊括了任何文件系统的常用功能集和行为。Linux可以支持很多种差异很大的文件系统,从DOS系统的FAT到Windows系统的NTFS,再到各种Unix风格文件系统和Linux特有的文件系统。VFS抽象层之所以能衔接各种各样的文件系统,是因为它定义了所有文件系统都支持的、基本的、概念上的接口和数据结构。同时实际文件系统也将自身的诸如“如何打开文件”,“目录是什么”等概念在形式上与VFS的定义保持一致。因为实际文件系统的代码在同一接口和数据结构下隐藏了具体的实现细节,所以在VFS层和内核的其他部分看来,所有文件系统都是相同的。
块设备中最小的可寻址单元是扇区。扇区大小一般是2的整数倍,最常见的是512字节。扇区的大小是设备的物理属性,扇区是所有块设备的基本单元——块设备无法对比它还小的单元进行寻址和操作,尽管许多块设备能够一次对多个扇区进行操作。
当一个块被调入内存时(也就是在读入后或等待写出时),它要存储在一个缓冲区中。每个缓冲区与一个块对应,它相当于是磁盘块在内存中的表示。由于内核在处理数据是需要一些相关的控制信息,所以每一个缓冲区都有一个对应的描述符。该描述符用buffer_head结构体表示,称作缓冲区头,在文件<linux/buffer_head.h>中定义,它包含了内核操作缓冲区所需要的全部信息。缓冲区头结构和各个域的说明:
struct buffer_head{
unsigned long b_state; //缓冲区状态标志
struct buffer_head *b_this_page; //页面中的缓冲区
struct page *b_page; //存储缓冲区的页面
sector_t b_blocknr; //起始块号
size_t b_size; //映像的大小
char *b_data; //页面内的数据指针
.
.
.
}
2017-2018-1 20179209《Linux内核原理与分析》第八周作业
标签:ext 定位 信息 question 共存 bsh for 视频 代码
原文地址:http://www.cnblogs.com/genius-sen/p/7834075.html