发现问题出在alloc_pid失败,分析内核代码,这个受限于kernel.pid_max参数。

  将参数调大到100000后,再次运行。

  继续通过strace跟踪,这次发现问题出在了mprotect函数

  这个问题是由于当个线程的mmap个数限制,受限于vm.max_map_count参数。

  将参数调大到100000后,再次运行,线程数明显增加了。
  其实这里面还有一个参数kernel.threads-max限制,由于系统默认将这个参数设置为800000,非常大,所以这个参数的影响一直没有保留出来。
  后面又犯贱把相关的参数都设置成800000,结果内存耗尽,系统直接没响应了。。。。
  3.3     正向分析
  直接分析copy_process代码
  copy_process
  3.3.1  内存限制
  dup_task_struct–>alloc_task_struct_node/alloc_thread_info_node/arch_dup_task_struct–>kmme_cache_alloc_node(slub.c)–>slab_alloc_node–>
  “CONFIG_MEMCG_KMEM” //这里也是一个坑,docker这种基于cgroup的也会影响,可能会因为分配给slub的内存不够用出现线程限制
  具体函数:
  alloc_pages—->__memcg_kmem_newpage_charge–>memcg_charge_kmem–>__res_counter_charge–>res_counter_charge_locked
  3.3.2  Threads-max参数限制
  if (nr_threads >= max_threads) // threads-max 参数影响
  3.3.3  Pid_max参数限制
  alloc_pid–>alloc_pidmap //pid_max参数影响
  3.3.4  单进程内存限制
  单个进程的线程数,受限于vm.max_map_count限制
  4.   总结
  /proc/sys/kernel/pid_max #操作系统线程数限制
  /proc/sys/kernel/thread-max  #操作系统线程数
  max_user_process(ulimit -u) #系统限制某用户下多可以运行多少进程或线程
  /proc/sys/vm/max_map_count #单进程mmap的限制会影响当个进程可创建的线程数
  /sys/fs/cgroup/memory/${cgroup}/memory.kmem #单个docker 内核内存的限制,可以影响task_struct等slab节点的申请,间接影响可创建的线程数