uc_day03

一,虛擬內存管理技術
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;
}







發佈了51 篇原創文章 · 獲贊 2 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章