• 忘掉天地
  • 仿佛也想不起自己
bingliaolongBingliaolong  2022-02-16 20:43 Aet 隐藏边栏 |   抢沙发  18 
文章评分 2 次,平均分 5.0

内存布局

内核空间

  1. 通常在最高的内存地址,用户态程序无法访问
  2. 操作系统保留的一部分内存,用于存储内核代码、设备驱动程序等
  3. 这部分内存一般不在普通应用程序的内存布局中明确显示,但确实存在并且用户态程序无法直接访问

栈区

  1. 由编译器自动分配释放,存放函数的参数值,局部变量等
  2. 由高地址向低地址增长

共享库段

  1. 共享库段的位置通常位于堆区之上,栈区之下,但这个位置是相对灵活的
  2. 共享库段可能根据操作系统的内存分配策略和随机地址空间布局(ASLR)的设置在不同位置加载,具体地址在不同运行时可能有所不同
  3. 共享库的代码段可能与可执行文件的代码段(Text Segment)在地址空间上接近
    1. 共享库的代码段虽然是独立的,但它通常加载到内存中与主程序的代码段相邻或接近的地方
    2. 共享库(如 .so 文件或 .dll 文件)在被程序加载时,其代码段会被映射到内存中的特定位置
    3. 共享库(如 .so 文件或 .dll 文件)中的全局变量、静态变量和常量通常有各自的内存区域
      这些区域会在共享库加载到内存时映射到特定的位置
  4. 其他
    1. 当系统加载同名的共享库时,它会根据共享库的具体内容(不仅仅是版本号,还包括文件路径、文件大小、时间戳等)来决定是否需要重新加载和映射该共享库

堆区

  1. 程序在运行期间用mallocnew申请的内存就是从堆区分配的
  2. 一般来说,new分配的变量是存放于堆内存中的,但是返回的指针变量是存放在栈中的
  3. 由低地址向高地址增长

静态区

  1. static定义的数据都存放在全局静态存储区中,不管是main函数之外定义的全局变量,还是子函数定义的局部变量,只要用static修饰了,就会存储在全局静态存储区中

    1. main函数之外定义的静态全局变量,程序中随处都可访问
    2. 子函数的静态局部变量,只在定义该变量的模块可见
  2. 细分

    1. 初始化的全局变量和静态变量区
      存放已初始化的全局变量和静态变量
    2. BBS区(也就是未初始化的全局变量和静态变量区)
      存放未初始化的全局变量和静态变量,在程序运行时会初始化为零
    3. 常量区
      存放只读数据,如字符串常量和 const 变量

代码区

  1. 代码区(Text Segment)存放程序的可执行代码,即编译后的机器指令
  2. 函数代码、常量字符串等通常都放在这个区域
  3. 程序的指令指针会指向该区域执行代码,通常该区域是只读的,以防止程序意外修改自己的代码

SendMessagePostMessage

  1. sendmessage是同步的

    1. postmessage是异步的
  2. sendmessage它等待消息被处理完了才返回,如果消息不被处理,发送消息的线程讲一直被阻塞

    1. postmessage只把消息放入队列,不管消息是否被处理就返回
  3. 如果在同一个线程内,sendmessage发送消息时,由USER32.DLL模块调用目标窗口的消息处理程序,并将结果返回

    1. sendmessage在同一线程中发送消息并不入线程消息队列
    2. postmessage发消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口
  4. 如果在不同的线程内,sendmessage发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在USER32.DLL模块内监视和等待消息处理,直到目标窗口处理完返回

总结

  1. 同一线程
    1. SendMessage 直接调用目标窗口过程,不涉及消息队列
    2. PostMessage 将消息放入线程的消息队列(如果目标窗口在主 UI 线程中,那么消息会放入主线程的消息队列)
  2. 不同线程
    1. SendMessage 会跨线程直接调用目标窗口的窗口过程,并等待消息处理完毕后返回,仍然不涉及消息队列
    2. PostMessage 将消息放入目标窗口所属线程的消息队列,立即返回,不等待处理结果

理解

  1. 上述所谓SendMessage的跨线程
    1. 如果是主UI线程给其他线程的窗口SendMessage 了一个消息,在消息被处理返回前,主线程一直处于阻塞状态
    2. 同样,如果是其他线程x给主UI线程的窗口SendMessage 了一个消息,在消息被处理返回前,其他线程x一直处于阻塞状态

单例的线程安全问题

  1. 饿汉式
    1. 系统一运行,就初始化创建实例,需要的时候,直接调用。(线程安全)
  2. 懒汉式
    1. 系统运行中,实例并不存在,只有当需要改实例的时候,才会去创建并使用实例。(需要考虑线程安全)
    2. 方法一:单例指针为空的时候,加锁,创建
    3. 方法二:C++11的内部静态变量的方式

跨进程传递结构体

通过消息

  1. 使用使用sendmessage发送WM_COPYDATA消息,然后把要传送的结构体放到LPARAM里面

进程间通信

  1. 管道pipe
    1. 用于具有亲缘关系的进程间通信
  2. 命名管道fifo
    1. 可以用于无亲缘关系的进程间通信
  3. 信号
    1. 用于通知接收进程有某事发生
  4. 消息队列
    1. 有足够权限的进程可以向消息队列中添加消息,被赋予读权限的进程可以从消息队列中读取消息
  5. 共享内存
    1. 使得多个进程可以访问同一块内存空间,是最快的IPC通信方式
  6. 信号量
    1. 主要作为进程间以及同一进程不同线程间的同步方式
  7. 套接字
    1. 可用于不同机器间的进程间通信

线程间通信

  1. 全局变量
  2. 互斥量
  3. 信号量
  4. 事件
  5. 临界区

code

实现1

实现2

优化

本文为原创文章,版权归所有,欢迎分享本文,转载请保留出处!

bingliaolong
Bingliaolong 关注:0    粉丝:0 最后编辑于:2024-08-27
Everything will be better.

发表评论

表情 格式 链接 私密 签到
扫一扫二维码分享