Linux 多线程应用 降低内存(VSZ)占用

本文探讨了嵌入式开发中内存紧张问题,通过分析进程内存消耗,发现主要在多线程栈上。作者尝试通过调整系统栈大小和细化到线程栈设置,将栈从8MB减小到1MB,显著减少了内存占用。

嵌入式开发的内存无疑是非常吃紧的。特别是一些老设备,之前的一台终端设备因为内存占用过高,出现了运行出错,进程管理的APP直接杀死了占用最高的媒体APP,导致视频输出出现异常。先优化一下VSZ好了。
于是进探索了内存优化之路。在确保长时间运行内存不会增加(没有内存泄漏)后,首先查看 /proc 下的进程 内存占用的smap 信息:

cat /proc/<pid>/smaps|grep -v ' 0 kB'

查看进程申请的内存详情
通过观察不难发现大量的内存占用都在栈上。由于这个APP是一个多线程进程,一个线程就有一个栈,导致了进程申请的内存大量被用于线程栈的申请上,每个栈8MB,仅10个线程就占用了100MB的虚拟内存空间。
stack mem
一个进程占用99MB内存,11个线程栈的内存占了88MB。那么方向就很明确了。减少栈的大小即可。
首先想到的是,直接进行全局的配置系统默认栈得大小,因为目前Linux程序的线程使用的都是默认的参数,即采用系统默认的栈大小进行开辟线程的栈。使用ulimit -s 指令在启动脚本加入:

ulimit -s 1024

以上就将系统默认栈设置为1024KB,单位是KB。启动系统,不巧的是,有些APP运行出现了异常,猜测界面APP使用了大量的变量,导致栈的溢出,APP直接就退出了。缩小系统栈还是有一定的风险,而且不知会不会引入其他的问题。
想着既然Linux系统一般都是使用pthread启动线程,而且子线程一般变量较少,不需要很大的栈空间,那么我们可以通过pthread_create的pthread_attr_t进行参数的设定设定进程生成的线程栈,达到缩小进程内存占用的目的。
将佘艳的线程生成

int thread::startThread(callable *c) {

	int const res = pthread_create(&handle_, 0, &posix_thread_proxy, static_cast<void*>(c));
	if (res != 0) {
		delete c;
		return -1;
	}

	return 0;
}

改为这样创建线程(这里的stacksize的单位是字节)

int thread::startThread(callable *c) {

	pthread_attr_t thread_attr;
	pthread_attr_init(&thread_attr);
	pthread_attr_setstacksize(&thread_attr, 1024*1024); ///< 1MB
	int const res = pthread_create(&handle_, &thread_attr, &posix_thread_proxy, static_cast<void*>(c));
	if (res != 0) {
		delete c;
		return -1;
	}
	pthread_attr_destroy(&thread_attr);

	return 0;
}

即可将原来的8MB栈大小改为1MB,效果显著。

top指令查看 左边为修改前,右侧为修改后
top
ps -o pid,comm,rss,vsz 指令查看 左边为修改前,右侧为修改后
ps
可以看到线程多的APP占用基本缩小了一半多。

<think>嗯,用户想了解如何在Linux下查看内存占用多的进程。这个问题挺常见的,可能用户遇到了系统内存不足的情况,或者想优化服务器性能。首先,我得回忆一下常用的命令,比如top、ps、htop,还有free之类的。不过用户明确问的是进程,所以free可能不太相关,它主要是看总体内存使用情况。 首先想到的是top命令,因为默认打开后,它会显示各个进程的内存和CPU使用情况。用户可能需要知道如何按内存排序,在top界面里按Shift+M可以按内存占用排序。不过用户可能不记得这些交互命令,所以需要给出具体的步骤。 然后是ps命令,结合排序选项。比如ps aux --sort=-%mem,这样可以根据内存使用率排序。不过得确认参数是否正确,有时候不同的系统可能有差异,比如有的用-rss或者其他的参数。可能需要检查一下man手册,不过一般ps aux --sort=-%mem是有效的。 还有htop,这是一个更友好的交互式工具,但可能不是所有系统都预装了。用户可能需要安装,所以如果用户没有的话,可能需要指导他们安装。比如在Ubuntu下用sudo apt install htop,CentOS用yum之类的。 另外,可以提到pmap工具,不过它更多是查看单个进程的内存映射,可能不太适合快速查看占用的进程。还有/proc/meminfo,但这也是整体信息,不是进程级别的。 还要考虑用户可能需要知道如何只显示前几个进程,比如结合head命令,例如ps aux --sort=-%mem | head -n 10,这样显示前10个内存使用的进程。 另外,需要解释输出中的各个字段,比如VSZ和RSS,VSZ是虚拟内存大小,RSS是实际使用的物理内存。用户可能更关心RSS,因为这是实际占用内存。 可能还要提到如何持续监控,比如使用top -d 1来每秒刷新,或者使用watch命令配合ps,比如watch -n 1 'ps aux --sort=-%mem | head -n 10',这样每隔一秒更新一次。 还要注意,有些进程可能有多个线程或者子进程,这时候可能需要更详细的参数,或者使用其他工具如smem,不过这可能属于进阶内容,用户可能暂时不需要。 最后,确保给出的命令正确无误,并且在不同发行版下都能使用。比如ps命令的参数是否一致,是否需要sudo权限等。比如某些情况下ps可能需要sudo来查看所有进程,但通常ps aux不需要。</think>在 Linux 系统中查看内存占用的进程,可通过以下步骤操作: --- ### 一、使用 `top` 命令(实时监控) ```bash top ``` 1. 启动后默认按 **CPU 占用**排序 2. 按下大写 `Shift + M` 立即按 **内存占用**排序 3. 关键列说明: - `%MEM`: 进程占用物理内存百分比 - `RES`: 实际使用的物理内存(单位 KB) - `VIRT`: 虚拟内存总量 --- ### 二、使用 `ps` 命令(静态快照) ```bash ps aux --sort=-%mem | head -n 10 ``` - **命令解析**: - `--sort=-%mem`: 按内存使用率降序排列 - `head -n 10`: 显示前 10 个进程 - **输出列说明**: - `USER`: 进程所有者 - `%MEM`: 内存占用百分比 - `RSS`: 实际物理内存占用(单位 KB) --- ### 三、使用 `htop` 工具(增强版交互式监控) ```bash htop ``` 1. 安装方法(如未预装): - Debian/Ubuntu: `sudo apt install htop` - CentOS/RHEL: `sudo yum install htop` 2. 交互操作: - 按 `F6` → 选择 `PERCENT_MEM` → 按内存排序 --- ### 四、查看 `/proc/meminfo`(分析内存详情) ```bash cat /proc/meminfo ``` - 查看系统级内存分配: - `MemTotal`: 总物理内存 - `MemFree`: 空闲内存 - `Buffers/Cached`: 缓存和缓冲区内存 --- ### 五、排查内存泄漏技巧 1. 定位内存进程后,用 `pmap` 分析内存映射: ```bash pmap -x <PID> # 替换<PID>为实际进程ID ``` 2. 持续监控内存变化: ```bash watch -n 1 'free -h' # 每秒刷新内存使用情况 ``` --- ### 六、示例输出解读 ```bash USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND mysql 1234 2.3 25.6 2872344 1.2g ? Ssl 09:00 5:23 /usr/sbin/mysqld java 5678 6.7 18.2 4231568 892m ? Sl 09:01 8:12 /usr/bin/java -Xmx2g ``` - `%MEM` 最的是 MySQL 进程(25.6%) - `RSS` 列显示 MySQL 实际占用 1.2GB 物理内存 --- 通过以上方法可快速定位内存瓶颈,建议组合使用 `top`(实时)和 `ps`(快照)进行交叉验证。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值