首页 > 代码库 > UnixC学习小结

UnixC学习小结

1.malloc工作原理:     malloc使用一个数据结构(链表)维护分配空间

    链表的构成:分配的空间/上一个空间数据/下一个空间/空间大小等信息.
    对malloc分配的空间不要越界访问.因为容易破坏后台维护结构.导致malloc/free/calloc/realloc不正常工作.
2.有关__stdcall __cdecl __fastcall
<1>.决定函数栈压栈的参数顺序. <2>.决定函数栈的清空方式   <3>.决定了函数的名字转换方式.
__cdecl
  这是编译器默认的函数调用转换方式,它可以处理可变参数的函数调用。参数的入栈顺序是从右向左。在函数运行结束后,由调用函数负责清理入栈的参数。在编译时,在每个函数前面加上下划线(_),没有函数名大小写的转换。即_functionname
  每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。
 
__fastcall
  有一些函数调用的参数被放入ECX,EDX中,而其它参数从右向左入栈。被调用函数在它将要返回时负责清理入栈的参数。在内嵌汇编语言的时候,需要注意寄存器的使用,以免与编译器使用的产生冲突。函数名字的转换是:@functionname@number没有函数名大小写的转换,number表示函数参数的字节数。由于有一些参数不 需要入栈,所以这种转换方式会在一定程度上提高函数调用的速度。
 
__stdcall
  函数参数从右向左入栈,被调用函数负责入栈参数的清理工作。函数名转换格式如下:_functionname@number
 
3.虚拟内存:      虚拟地址与物理地址映射的时候有一个基本单位: 4k  一个内存页.     如果虚拟地址没有映射到物理地址,试图用指针访问必定发生段错误
4.分配释放内存函数:      int brk(void *end);//分配空间,释放空间
     void *sbrk(int size);//返回空间地址 
            sbrk(int  size)
    sbrk与brk后台系统维护一个指针.
    指针默认是null.
    调用sbrk,判定指针是否是0,是:得到大块空闲空间的首地址初始化指针.
5.映射虚拟内存函数:
  mmap(分配)/unmap(释放)
 
void *mmap(
void *start,//指定映射的虚拟地址 0由系统指定开始位置)
size_t length,//映射空间大小 pagesize倍数
int prot,//映射权限  PROT_NONE | PROT_READ PROT_WRITE PROT_EXEC
int flags,//映射方式
int fd,//文件描述符号
offset_t off);//文件中的映射开始位置(必须是pagesize的倍数)
 
映射方式:
内存映射:匿名映射。
文件映射:映射到某个文件   只有文件映射最后两个参数有效。
 
MAP_ANONYMOUS
MAP_SHARED   MAP_PRIVATE(二选一)
 
 
 
6.编译工具与动态库:
 
<1> gcc
-o  输出文件名
-O  -O0 -O1 -O2 -O3 编译优化
-g  -g0 -g1 -g2 -g3  产生调试信息
-W  all  error  
-Wall  显示所有警告 
-Werror   把警告当错误
-w  关闭警告
 
 
 
-c  只编译不连接
-E  预编译
-S  汇编
 
-D 在命令行定义宏。
在代码中定义宏
在命令行定义宏
 
-x  指定编译的语言类型
c++
c
.S
none 自动判定
-std=C89
C99
 
 
 
编译过程:-E  -c -S   自动调用连接器
连接器 ld
补充:
.c
.cpp
.CC
.h
.hpp
.o
.a
.so
.i    预编译文件
.s  汇编文件
 
 
<2>
1.编译过程(*.a   achieve)
1.1.编译成目标文件
-static  可选
gcc -c -static 代码文件.c
 
1.2.归档成静态库
ar工具
ar -r  ||  -t
ar -r 静态库文件  被归档的文件
 
nm工具(察看函数符号表)
nm 静态库或者动态库或者目标文件或者执行文件
1.3.使用静态库
gcc 代码  静态库 
 
2.库的规范与约定
库命名规则:
lib库名.a.主版本号.副版本号.批号
lib库名.a
库使用规则
-l 库名
-L 库所在目录
 
 
<3>.动态库的编译
 
1.什么是动态库?(共享库)
动态库是可以执行,静态库不能执行
但动态库没有main,不能独立执行。
动态库不会连接成程序的一部分。
程序执行的时候,必须需要动态库文件。
 
2.工具
       ldd  察看程序需要调用的动态库
ldd 只能察看可执行文件.
readelf -h 察看执行程序头.
nm   察看库中的函数符号
 
3.动态库的编译
3.1.编译
-c -fpic(可选)
3.2.连接
shared
4.使用动态库
gcc 代码 动态库文件名
gcc 代码   -l库名 -L动态库所在路径
 
标准命名规则:
lib库名.so
        lib库名.a
-l 库名  -L 库所在路径
 
<5>使用libdl.so库
动态库加载的原理 动态库中函数的查找已经封装成库libdl.so
 
dlopen  打开一个动态库
dlsym 在打开动态库找一个函数
dlclose 关闭动态库
//dlerror 返回错误
 
 
7.make工具的使用:
(1). vi  demo.mk
(2)编辑:  demo:
                           gcc -c -fpic test1.c
                           gcc -c -fpic test2.c
                           gcc test1.o  test2.o  -shared  -o libtest.so
                           gcc main.c -l test -o main -L.
(3).执行demo.mk文件:
               make -f demo.mk demo
注意:须将libtest.so 库文件拷贝到/lib或usr/lib目录下
 
 
 
8.使用main方法参数获得环境变量:(直接获取可以用env)
 
int main(int argc,char*argv[],char**arge)
{
        while(*arge)
       {
              printf("%s\n",*arge);
              arge++;
       }
}
 
 
 
9.IO基础
 
<1>.认识内核对象
不允许访问内核设备和内存,
但可以通过内核系统函数去访问.
对每个内核对象进行编号ID.
如果访问内核对象,只能通过ID.
编程模型:
申请得到一个ID
在内核系统函数中使用ID得到对应内核对象数据
<2>.怎么访问文件
使用函数,传递一个文件,系统打开文件,加载文件数据,
返回一个ID.
使用函数,传递ID,得到数据.
使用函数传递ID,告诉系统释放文件.
 
ID:文件描述符号.file description (fd)
 
每个程序执行的时候都有一个目录,存放打开的文件描述符号
 
<3>.每个程序默认打开三个文件设备:
0:标准输入
1:标准输出
2:错误输出
 
<4>.操作文件描述符号
ssize_t write(int fd,
void *buf,//要写入内核对象的数据
size_t size);//写入数据大小
返回:
>0 实际写入的数据
-1 写入错误
 
ssize_t read(int fd,
void *buf,//返回数据的空间
size_t size);//空间大小
返回:
>0:实际读取的数据
=0:碰到文件结束符号EOF (ctrl+d)
-1:读取错误
 
建议:
0:输入
1:输出
2:错误输出
<5>.linux系统下文件的类型:
       目录文件d
       普通文件f
       字符设备文件c
       块设备文件b
       软连接文件l
       管道文件p
       socket文件s
 
 

UnixC学习小结