linux内存高级管理rbrk,brk函数

 malloc()和free()
   free()只能保证释放虚拟内存地址,但不保证解除物理内存的映射,而且,最后33个内存页的映射是无法free()的,进程结束才能解除最后33个内存页的映射。free()不一定释放物理内存,但一定释放虚拟内存。
  在应用中,malloc()和free()正常使用即可
 
  sbrk() 和 brk()
   sbrk() brk()是Unix/Linux系统函数,因此windows不识别。
   sbrk()和brk()底层维系了一个位置(position),通过位置的移动分配/回收内存
   void* sbrk(int increment)
   参数increment是位置移动的增量,如果正数,位置向后移动;如果负数,位置向前移动;如果为0,位置不移动,返回当前的位置。
   返回值,成功返回 移动之前的位置,失败返回 (void*)-1。
   释放内存、删除文件其实 都不清除数据,数据在放入新元素时被覆盖。
   brk()和sbrk()都是可以 分配也可以回收内存的函数。
   sbrk()分配内存时简单,回收内存时需要计算,比较麻烦,而brk()正好相反。
   int brk(void* pos)是直接指定位置。
    pos就是新位置,与原位置在哪里无关。
   返回值 0 代表成功,-1代表失败。

   brk()直接移动位置到新位置,而不管原来位置在哪里,类似 绝对路径。

sbrk()例子

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

int main(){
  void* p1 = sbrk(4);//p1指向初始位置,新位置在4字节
  void* p2 = sbrk(4);//映射一个内存页
  void* p3 = sbrk(4);// 正数代表分配内存
  void* p4 = sbrk(4);//位置在16
  *(int*)p4 = 100;
  printf("p1=%p,p2=%p,p3=%p,p4=%p\n",p1,p2,p3,p4);
  sbrk(-4);//负数代表 释放内存,返回值没有意义
  sbrk(-8);
  printf("%d\n",*(int*)p4);
  void* p = sbrk(0);//0取当前位置
  printf("p=%p\n",p);
  p = sbrk(4093);//4093+4 = 4097 超过一个字节,多一页
  printf("pid=%d\n",getpid());
  sleep(15);
  printf("释放1字节内存\n");
  sbrk(-1);  sleep(15);//少了一页
  sbrk(-4096); printf("全部释放\n");//解除映射
  while(1);
}



brk()例子

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

int main(){ 
  void* p = sbrk(0);//先取初始位置,以后才能brk
  int r = brk(p+4);//分配了4个字节
  if(r == -1){ perror("brk"); return -1; }
  brk(p+8);//重新分配了4个字节
  brk(p+4);//回收了4个字节
  int* pi = p;//从初始位置开始
  *pi = 100;
  //重新分配10个字节,放字符串 "abcde"
  char* s = sbrk(0);
  brk(s+10);//分配10字节
  //s = "abcde";//有问题,指向了只读区,堆区内存泄漏
  strcpy(s,"abcde");
  double* pd = sbrk(0);//取首地址
  brk(pd+1);//pd+1 移动了8个字节
  *pd = 1.0;
  printf("%d,%s,%lf\n",*pi,s,*pd);
  brk(pd);//释放double的空间
  brk(s);
  brk(pi);//全部释放
}


#include <stdio.h>
#include <unistd.h>
#include <string.h>
//brk和sbrk 结合使用
int main(){
  int* pi = sbrk(4);
  char* ps = sbrk(10);
  double* pd = sbrk(8);
  *pi = 100;
  strcpy(ps,"abcde");
  *pd = 1.0;
  printf("%d,%s,%lf\n",*pi,ps,*pd);
  
  brk(pi);//相当于全部都释放了
}


### 解释 XUARTPS 事件处理逻辑 #### 接收缓冲区满 (RXFULL) 和 超时 (TOUT) 对于 `XUARTPS_IXR_RXFULL` 和 `XUARTPS_IXR_TOUT` 这两个中断标志位,在 Zynq 的 AXI UART PS 设备中具有特定的作用。 - **接收缓冲区满 (`XUARTPS_IXR_RXFULL`)** 当硬件检测到 FIFO 缓冲区已满或达到设定阈值时,会触发此中断。这意味着有大量数据被接收到并存储在内部的接收FIFO中,应用程序应当尽快读取这些数据以防止溢出。通过调用 `XUartPs_SetInterruptMask` 并传递相应的掩码参数来使能这个中断[^2]。 - **超时 (`XUARTPS_IXR_TOUT`)** 此中断会在指定时间内未接收到新字符的情况下发生。具体来说,如果连续32个波特率周期内没有任何新的字符到达,则会产生一个超时条件,并触发对应的中断信号。这有助于及时响应少量间歇性的输入流,即使它们之间存在较长间隔也能确保不会遗漏任何有效载荷。同样地,也需要利用 `XUartPs_SetInterruptMask` 来激活这种类型的中断[^4]。 ```c // 设置中断屏蔽寄存器,允许 RXFULL 和 TOUT 中断 u32 IntrMask; IntrMask = XUARTPS_IXR_RXFULL | XUARTPS_IXR_TOUT; if (UartInstPtr->Platform == XPLAT_ZYNQ_ULTRA_MP) { IntrMask |= XUARTPS_IXR_RBRK; } XUartPs_SetInterruptMask(UartInstPtr, IntrMask); ``` 一旦上述两种情况之一满足,即发生了接收缓冲区满或是超时时,处理器将会执行预先注册好的中断服务例程(ISR),通常是在初始化阶段通过如下语句完成: ```c // 注册 ISR 处理函数 XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)UartPs_Intr_Handler, UartInstPtr); ``` 在这个ISR里边,应该检查具体的中断源(比如是否是因为 RXFULL 或者 TOUT),进而采取适当的动作,像清空中断状态、获取最新接收到的数据等操作。 ```c void UartPs_Intr_Handler(void *CallBackRef){ XUartPs *InstancePtr = (XUartPs *) CallBackRef; // 获取当前发生的中断原因 u32 PendingIntr = XUartPs_GetInterruptStatus(InstancePtr); if(PendingIntr & XUARTPS_IXR_RXFULL){ // 清除 RXFULL 中断标记 XUartPs_ClearInterruptStatus(InstancePtr, XUARTPS_IXR_RXFULL); // 执行必要的动作,例如读取数据 while (!XUartPs_IsReceiveEmpty(InstancePtr)){ char data = XUartPs_ReadReg(InstancePtr->Config.BaseAddress, XUARTPS_FIFO_OFFSET); // 对 'data' 做进一步处理... } } if(PendingIntr & XUARTPS_IXR_TOUT){ // 清除 TOUT 中断标记 XUartPs_ClearInterruptStatus(InstancePtr, XUARTPS_IXR_TOUT); // 可选:在此处实现针对超时的具体行为 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值