uc_day03

来源:互联网 发布:网络电视外置无线网卡 编辑:程序博客网 时间:2024/06/05 10:21
一,虚拟内存管理技术
1,Linux操作系统采用虚拟内存管理技术
真正的物理地址是接触不到的,真正的物理地址只有操作系统才能
我们平时所说的地址是虚拟地址,也称为逻辑地址


2,段错误问题
A,对内存空间的操作超出权限的限制,会导致段错误
比如:写只读空间
B,访问没有对应物理空间的虚拟地址,会导致段错误


3,堆空间分配
malloc 会在后台维护一个双向链表的数据结构,并且每次malloc
会在结束位置有标记(12Byte),越界访问会破坏标记,从而导致内存释放出现问题。
总之,使用malloc时不要越界访问。


二,内存页面管理
page.c


#include<stdio.h>
#include<stdlib.h>
int main(){
  int* p = malloc(4);
  *p = 100;
  *(p+100) = 100;  
  return 0;
}


操作系统分配物理内存空间时,会按页为单位进行分配。一般系统
一页为4096Bytes。操作系统分配好物理空间后,会给进程分配虚拟内存地址
与物理空间一一对应起来,这个叫内存映射。


对于malloc来说,操作系统第一次会直接分配33个页面的物理内存空间并映射
malloc分小内存和大内存分配




三,brk/sbrk的虚拟内存管理----UNIX内存分配函数
sbrk仅仅记录当前的位置,一个一个页面的分配的。维护的后台位置是os在


void* sbrk(int size)
-size=0 返回sbrk/brk上次的末尾地址
-size>0 分配内存空间,返回上一次末尾地址
-size<0 释放空间


#include<unistd.h>


sbrk.c


#include<stdio.h>
#include<unistd.h>


int main(){
  void* p1 = sbrk(4);//分配四个字节的空间 
  void* p2 = sbrk(4);//页面不会再分配
  void* p3 = sbrk(4);


  sbrk(-4);//释放4个字节
  void* cur = sbrk(0);//返回当前位置
    
  return 0;
}




ps aux
----------------------------------------------------------------
int brk(void* end_data_segment);
成功:返回0
失败:-1


#include<stdio.h>
#include<unistd.h>


int main(){
  void* p = sbrk(0);//获取当前位置
  printf("p=p%\n",p);
  brk(p+4);//分配了4个字节的空间
  brk(p+8);//又分配了4Bytes
  brk(p+4);//释放4Bytes


  char* str = sbrk(0);
  brk(str+10);
  strcpy(str,"abcdefg");
  
  brk(p);//释放所有的空间
  /*
   brk(p+14);
   strcpy(p+4,"abcdefg");
   char* str = p+4;
       
  */
  
}


一般情况下,我们使用sbrk分配空间,brk释放空间
#include<stdio.h>
#include<unistd.h>
#include<string.h>
int main(){
  void* p = sbrk(4);
  int* pi = p;
  *pi = 100;
  //放一个doulbe
  double* pd = sbrk(sizeof(double)):
  *pd = 3.14;
  //放一个字符串hello
  char* str = sbrk(10);
  strcpy(str,"hello");
  brk(p);//释放所有空间
  return 0;
}


四,mmap函数-----内存映射函数,只做内存映射
#include<sys/mman.h>
void *mmap(void *start,size_t length,int prot,int flags,
int fd,off_t offset);


*start:开始映射的虚拟内存空间
prot:权限
flags:标记
fd:文件描述符
offset:映射文件偏移量
返回值是映射好的首地址




mmap.c
#include<stdio.h>
#include<sys/mman.h>


int main(){
  //映射一片内存空间
 void* p =  mmap(
   sbrk(0)或者0,//映射好的空间的首地址(虚拟地址),0为放弃指定地址的权利,让操作系统找
   4,//映射空间的大小,按页面映射,故按页面对齐(不够一页则补齐)
   PROT_READ | PROT_WRITE,//代码区内存空间一般需要执行权限      
   MAP_SHARED | MAP_ANONYMOUS,//MAP_PRIVATED与MAP_SHARED必须选其一,映射到内存哪个都无所谓,如果映射到文件需要选择
                 //MAP_ANONYMOUS意味着映射到物理内存,没有这个选项,意味着映射到文件,文件可以当内存,指针指来指去
   0,//文件描述符
   0//文件偏移量
);


 //if(p == (void*)-1)
  if(p == MAP_FAILED){
     perror("内存映射失败");
     return -1;
  }


  munmap(p,4);//结束映射
  return 0;
}




五,系统调用
硬件
||
Kernel:内核,是大量驱动程序,系统功能程序....
||
系统调用:内核给外界公开的访问接口,本质上是一些函数
函数调用时进程进入系统态




六,文件
1,特殊文件
/dev/null 空设备文件  代表不存在的文件 Unix黑洞


cat /dev/null > a.txt//清空a.txt


find / -name perl 2>/dev/null


/dev/tty 输入输出设备


2,文件描述符
值为一个非负整数
用于表示一个打开文件


1-标准输出
2-错误输出
0-标准输入




#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>




-----------------------------------------------------------
#include<stdio.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<stdlib.h>


//创建三个参数,非创建两个参数
int main(){
  int fd = open("a.txt",O_RDWR|O_CREAT,0666);
  if(fd == -1){
    perror("创建文件失败");
    exit(-1);
  }
  printf("文件创建成功\n");




  int fd2 = open("a.txt",O_RDONLY);
  if(fd2 == -1){
  perror("打开文件失败");
  exit(-1);
  }
  printf("打开文件成功\n");
  return 0;
}
创建出来的文件权限是644,屏蔽了本组和其他人写的权限
umask 022


3,open函数
int 文件描述符 = open(文件名,int flags);
flags:
     O_RDONLY
     O_WRONLY
     O_RDWR


     O_CREAT:创建文件,必须有第三个参数(权限)
     O_EXCL:和O_CREAT一起,如果创建的文件已经存在,返回-1
     O_TRUNC:和O-CREAT一起使用,如果创建的文件已经存在,删除此文件,创建新的文件




3,write函数
man -s2 write
ssize_t write(int fd,const void *buf,size_t count);




#include<stdio.h>
#include<unistd.h>
#include<fcnl.h>
#include<stdlib.h>
#include<string.h>


int main(){
 int fd = 
    open("a.txt",O_RDWR | O_CREAT | O_TRUNC,0666);
 if(fd == -1) perror("文件创建失败"),exit(-1);
 int res = write(fd,"Hello World!",strlen("Hello World!"));
 if(res == -1){
   perror("写文件失败");
   exit(-1);
 }
 printf("成功地向文件写了%d字节的数据",res);
 write(1,"Hello world!\n",13);//显示在了显示器上了
 return 0;
}


3,read函数
ssize_t read(int fd,void* buf,size_t count);


#include<stdio.h>
#include<string.h>
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>


int main(){
   int fd = open("a.txt",O_RDONLY);
   if(fd == -1){
   perror("打开文件失败");
   exit(-1);
   }
   char buf[100] = {};
   int res = read(fd,buf,sizeof(buf));
   if(res == -1){
     perror("读取文件失败"); 
     exit(-1);
   }
   printf("从文件中读到%d字节的数据\n",res);
   printf("内容:%s\n",buf);
   return 0;
}







0 0