linux上可以运行多少进程 && 一个进程可以开辟多少线程?

本文探讨了Linux系统上可以运行的进程数量及其限制,通常由系统资源决定,可通过特定命令查看。对于一个进程,可以开辟的线程数量受限于调用栈大小,一般在300左右。可以通过调整系统参数进行一定的扩展。

linux上可以运行多少进程 && 一个进程可以开辟多少线程?

 

这个问题我们被困扰了很久,只知道一个大致数字,而没有很准确的结果,今天我们就自己测试一下?

首先我们需要了解:

  • 进程:是系统分配资源的单位,是运行中的程序,是程序+指令+资源的一组集合。
  • 线程:是cpu调度执行的最小单位,可以看作轻量级进程,线程是进程中的一条执行序列,我们可以通过线程库创建线程

 

我们可以想到,进程既然是系统分配资源的单位,那么当然会有一个数量限制,系统的资源也不是无限的,那么线程同理,线程是进程的一条执行序列,那么当然也会有一个数量限制了。

 

我们直接进入正题,一个一个解决:

第一个问题:linux上可以运行多少进程?

①:我们可以通过特定命令在Linux上查看一下系统的进程限制

 

可以看到,我自己linux系统上上限设置的是1024个,也就是说我的计算机上最多可以有1024个进程,但是这是一个软限制,是可以进行修改的,比如我们可以通过ulimit -u 4096来设置为4096个:

 

②:我们也可以通过pid的大小限制来判断一个进程的数量范围

我们在上一篇博客中探讨过,pid是一个短整型short,这个值的大小为PID_MAX,也就是32767,其中0~299是为系统进程(包括内核线程)保留的。

我们可以通过命令进行查看:

当然,这里数字只是表示理论上的限制,但是由于现实中计算机内存等系统资源的限制,是根本不会有这么多的进程同时打开的。

 

 

第二个问题:linux上一个进程可以开辟多少线程?

①:我们知道线程除了调用栈是自己独有的,其他的资源全部共享进程,所以限制一个进程可以开辟线程的数量的关键点就在于这个调用栈上。

我们可以通过命令查看一下系统会为一个线程调用栈分配多少资源:

 

我们可以看到结果是10240,单位是kbytes,表示线程调用栈大小为10M,而我们知道32位操作系统4G虚拟内存空间中除了1G内核空间还有3G的用户空间,所以一个进程可以开辟的线程数目就是用3G/10M,结果大致是300左右,但是实际上会比这个数字小一些,因为不能用户空间全部分配给你,肯定还有其他进程需要资源。

当然,我们可以通过ulimit -s来设置stack size,将10M变小一些就可以开辟更多的线程了。

 

②:我们通过代码自己进行测试一番,看到底能开辟多少线程

代码如下:

#include <stdio.h>
#include <pthread.h>
#include <assert.h>

void* func(void *arg)
{
}

int main()
{
	int i = 0;
	pthread_t id;

	while(1)
	{
		int res = pthread_create(&id, NULL, func, NULL);
		if(res != 0)
		{
			break;
		}
	
		printf("已开辟线程数:%d\n", i++);
	}
	return 0;
}

 

我们可以看到测试结果为301个:

 

符合上述预估的值,我们计算机也就大致开辟300左右的线程。

<think>我们正在讨论进程如何创建线程以及相关机制。根据引用[1],线程进程内的执行单元,共享进程的堆和方法区资源,但有自己的程序计数器、虚拟机栈和本地方法栈。引用[3]指出,在Windows平台,线程是最小的执行单位,由主线程启动工作线程。 现在,用户的问题是:进程如何创建线程线程开辟的机制是什么? 回答步骤: 1. 解释线程创建的基本机制:进程通过调用操作系统的API(如Windows的CreateThread或POSIX的pthread_create)来创建线程。 2. 描述线程创建时操作系统内部的操作:包括分配线程控制块(TCB)、设置线程上下文(如程序计数器、栈指针)、分配栈空间等。 3. 说明线程创建后的状态:新建的线程进入就绪状态,等待调度执行。 4. 结合引用[1]和[3]的内容,强调线程共享进程资源但有自己的栈和寄存器状态。 5. 可以简要提及用户级线程和内核级线程(引用[4]提到多对一模型,但这里我们主要关注内核级线程)。 注意:引用[2]提到线程间通信方便,因为共享地址空间,但这不是创建机制的直接内容,可以略过。 根据以上思路,组织回答如下:</think>### 进程创建线程的机制详解 进程创建线程的核心机制可分为三个层次,下面结合操作系统原理和引用内容逐步说明: #### 1. **编程接口层(用户可见)** 进程通过操作系统提供的API创建线程: - **Windows系统**:调用`CreateThread()`系统函数 - **Linux/POSIX系统**:调用`pthread_create()`库函数 ```c // POSIX线程创建示例 #include <pthread.h> void* thread_func(void* arg) { /* 线程逻辑 */ } int main() { pthread_t tid; pthread_create(&tid, NULL, thread_func, NULL); // 创建新线程 pthread_join(tid, NULL); // 等待线程结束 } ``` 此时操作系统收到线程创建请求,进入内核态处理[^3]。 #### 2. **内核管理层(操作系统级)** 内核执行以下关键操作(引用[1][3]): 1. **分配线程控制块(TCB)** 创建线程专属数据结构,存储: - 程序计数器(PC):指向线程入口函数地址 - 栈指针(SP):指向线程独立栈空间 - 寄存器状态 $$ \text{TCB} = \langle \text{PC}, \text{SP}, \text{寄存器组}, \text{状态} \rangle $$ 2. **分配线程栈空间** - 在进程地址空间中分配独立栈区(通常8-10MB) - 栈用于存储局部变量、函数调用链(与主线程隔离) 3. **设置共享资源指针** 将TCB中的资源指针指向进程的: - 堆内存空间 - 打开的文件描述符 - 全局变量区 ```mermaid graph LR A[进程] --> B[堆内存] A --> C[文件描述符表] A --> D[全局变量] T[线程TCB] -->|共享指针| B T -->|共享指针| C T -->|共享指针| D ``` 4. **调度就绪** 将新线程加入就绪队列,等待CPU调度[^3] #### 3. **硬件执行层(CPU级)** 线程切换时CPU执行: 1. 保存当前线程上下文(寄存器值→TCB) 2. 加载新线程上下文(TCB→寄存器) 3. 跳转到新线程的程序计数器位置 $$ \text{切换开销} \propto \text{寄存器数量} \quad (\text{远小于进程切换}) $$ 因为无需切换页表、文件描述符等资源(引用[1]) #### 关键特性总结 1. **资源隔离与共享** - 共享:堆内存、全局变量、静态变量(需同步锁) - 隔离:栈空间、寄存器状态、程序计数器(引用[1][2]) 2. **线程生命周期** ```mermaid stateDiagram-v2 [*] --> 新建 : CreateThread() 新建 --> 就绪 : 资源分配完成 就绪 --> 运行 : CPU调度 运行 --> 阻塞 : I/O请求 阻塞 --> 就绪 : I/O完成 运行 --> 终止 : 线程结束 ``` 3. **主线程的特殊性** - 由操作系统自动创建(进程启动时) - 终止时默认结束整个进程(除非设为守护线程) - 可创建工作线程实现并发(引用[3]) > ⚠️ **风险提示**:线程崩溃会导致整个进程终止(引用[1]),因此需通过互斥锁、信号量等同步机制保护共享资源(引用[2])。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值