7/21复习1次

目录

malloc如何申请内存

线程和进程

线程与进程的区别:

进程间通信方式:

线程间通信方式:

死锁如何解决:

使用mmap的场景包括:


int fun1(){  
    union test{   
        char c;   
        int i; 
    };  
    test t; t.i = 1;  
    //如果是大端,则t.c为0x00,则t.c != 1,反之是小端  
    return (t.c == 1);  
}  

c 没有 赋初值,所以没有 有效字节 

malloc如何申请内存

  • malloc 通过 brk() 方式申请的内存,free 释放内存的时候,并不会把内存归还给操作系统,而是缓存在 malloc 的内存池中,待下次使用
  • malloc 通过 mmap() 方式申请的内存,free 释放内存的时候,会把内存归还给操作系统,内存得到真正的释放
  • 频繁通过 mmap 分配的内存话,不仅每次都会发生运行态的切换,还会发生缺页中断(在第一次访问虚拟地址后),这样会导致 CPU 消耗较大

    为了改进这两个问题,malloc 通过 brk() 系统调用在堆空间申请内存的时候,由于堆空间是连续的,所以直接预分配更大的内存来作为内存池,当内存释放的时候,就缓存在内存池中。

    等下次在申请内存的时候,就直接从内存池取出对应的内存块就行了,而且可能这个内存块的虚拟地址与物理地址的映射关系还存在,这样不仅减少了系统调用的次数,也减少了缺页中断的次数,这将大大降低 CPU 的消耗

class LRUCache {
    list<pair<int, int>> cache;//创建双向链表
    unordered_map<int, list<pair<int, int>>::iterator> map;//创建哈希表
    int cap;
public:
    LRUCache(int capacity) {
        cap = capacity;
    }

    int get(int key) {
        if (map.count(key) > 0){  // 已经存在
            auto temp = *map[key];
            cache.erase(map[key]);
            map.erase(key);

            cache.push_front(temp); 
          //push_front() 在列表的开头插入新元素并将列表的大小增加一
            map[key] = cache.begin();//映射头部
            return temp.second;
        }
        return -1;
    }

    void put(int key, int value) {
        if (map.count(key) > 0){ //已经存在
            cache.erase(map[key]);
            map.erase(key);
        }
        else if (cap == cache.size()){ //满了
            auto temp = cache.back();
            map.erase(temp.first);
            cache.pop_back(); //pop_back:移除末元素


        }
        cache.push_front(pair<int, int>(key, value)); //新建
        map[key] = cache.begin();//映射头部
    }
};

std::move 就是实现了 浅拷贝,同时消灭 原本的 被拷贝者 地址中放的东西

线程和进程

进程:  程序运行的实例,资源分配的单位 ,三种、五种基本状态  发生页表的切换过程开销比较大,

线程:CPU调度的最小单位,线程是进程当中的一条执行流程

线程与进程的区别

(1)一个线程从属于一个进程;一个进程可以包含多个线程。

(2)一个线程挂掉,对应的进程挂掉;一个进程挂掉,不会影响其他进程。

(3)进程是系统资源调度的最小单位;线程CPU调度的最小单位。

(4)进程系统开销显著大于线程开销;线程需要的系统资源更少。

(5)进程在执行时拥有独立的内存单元,多个线程共享进程的内存,如代码段、数据段、扩展段;但每个线程拥有自己的栈段和寄存器组。

(6)进程切换时需要刷新TLB并获取新的地址空间,然后切换硬件上下文和内核栈,线程切换时只需要切换硬件上下文和内核栈。

(7)通信方式不一样。

孤儿进程:孤儿就是没有爸爸,所以就是父进程退出,而它的子进程还在继续,这些进程就会成为孤儿进程

消息队列:保存在内核中的消息链表,通信过程中存在用户态和内核态之间的数据拷贝开销

                   消息队列的声明周期随着内核操作系统关闭 或者 关闭 消息队列的操作,而关闭,不会随着进程的关闭而关闭 

进程间通信方式:

线程间通信方式:

        临界区 ,每个线程都会访问的那段代码

        互斥量: 拥有互斥对象的线程才可以访问

死锁如何解决:

        资源一次性分配,不要获得一定资源,又想获得已经被其他进程占有的资源    

        也可以剥夺 已被进程占有的资源

        资源的分配,递增请求,释放相反

使用mmap的场景包括:

  1. 文件的映射:可以将文件映射到进程的地址空间,进而实现对文件的读写操作。

  2. 共享内存:多个进程可以通过映射同一块物理内存区域实现共享内存,从而进行进程间通信。

  3. 匿名映射:创建一个无关联的映射区,通常用于大块的动态内存分配。

  4. 零拷贝:在网络编程中,使用mmap可以减少数据从内核空间到用户空间的拷贝次数,提高数据传输效率。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值