C++多线程操作,pthread_create()创建失败?解决:分析

在做毕设的时候遇到了一个多线程问题。
场景中需要传出一个数据用于显示。显示就是用上一篇文章《数码管 二位 2位共阳 显示两个不同的数字》中提到的2位共阳极数码管,由于显示数据是需要有一段时间的暂留,来达到用户观看舒适的效果。
用于数据显示的代码如下

 

void *display_temperature(void *arg)
{
    if(wendu_gate){
        wendu_gate = false;
        int i;
        int temperature = *(int *)arg;
        if(temperature > 0 && temperature < 10){
           for(i = 0;i<20;i++){
               display_second(temperature);
               delay(49);
           }
        }else{
            int temperature_one = temperature / 10;
            int temperature_two = temperature % 10;
            for(i = 0;i<500;i++){
               display_second(temperature_two);
               display_first(temperature_one);
            }
        }
        for(i = 0 ;i < 10 ; i++){
            digitalWrite(i, LOW);
        }
        wendu_gate = true;
    }
    return ((void *)0);
}

 

暂未发现到有什么会影响到进程无法创建的问题。当该段代码运行结束时就会返回一个 0

实际使用了非常愚蠢的办法,手动调用了180+ 的线程。如果没有数错是 182,就无法继续创建线程了。

通过命令查看每个线程的占用的栈空间大小 ulimit -a

core file size(blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 6994
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files(-n) 1024
pipe size(512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority(-r) 0
stack size(kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes(-u) 6994
virtual memory(kbytes, -v) unlimited
file locks(-x) unlimited

上面可以看到 stack size819200 bytes

PcDuino3B 的内存为 1GB

182 * 8 = 1456 明显已经把虚拟内存也占用了。

再也无法创建线程了,除非之前的进程有自己终止掉的。

网上给出了两个解决方案(原话复制)

1. 使用ulimit -s 1024*1024命令,将线程栈大小临时设置成1M,经过试验能同时创建2000个线程了。
2. 使用pthread_attr_setstacksize在程序中改变线程栈大小。

方案一说了,可以真实创建更多的线程了。可这并不能在根本上解决问题。一旦达到这个临界点还是无法继续创建。

方案二说 使用pthread_attr_setstacksize 在程序中改变线程栈大小,这好像同上面方案一样,还是无法在根本上解决问题。

毕设是需要一个健壮的代码来自动终止线程达到效果。


还在研究中…… 2016年12月18日 22:27

搞定之后来更新。

2016年12月18日 22:45
使用线程测试

#include
#include
#include
using namespace std;
int ledaaaa = 1;
int ma = 1;
void *led(void *arg){
cout <<"--------------------------------------" << ledaaaa << "------------------------"<< endl;
ledaaaa ++;
return ((void *)0);
}
void setup()
{
 
}
void loop()
{
int xxxxx;
pthread_t thread;
pthread_create(&thread, NULL, &led, &xxxxx);
pthread_testcancel();
cout << ma << endl;
ma++;
}

 

发现子线程只能进行到 379

这正好是上面的说的182的 两倍多一点(之前的182是因为我加了两个子线程 led 跟 温度)


多线程 非阻塞

#include
#include
#include
#include
#include
using namespace std;
int ledaaaa = 1;
int ma = 1;
 
pthread_t thread;
pthread_attr_t attr;
 
void *led(void *arg){
cout <<"led:" << ledaaaa << "------------------------"<< endl;
ledaaaa ++;
int i;
for(i=0;i<10;i++){
cout << i << endl;
}
pthread_exit(0);
}
 
void setup()
{
 
}
 
void loop()
{
int xxxxx;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, led, NULL);
pthread_attr_destroy(&attr);
cout << "ma:" << ma << endl;
ma++;
}

 


多线程非阻塞

/
//Cup.cpp
//CPP
//
//Created by Mr.Sin on 16/12/18.
//Copyright © 2016年 Mr.Sin. All rights reserved.
//
 
#include
#include
#include
#include
using namespace std;
 
pthread_t thread;
pthread_attr_t attr;
 
const int adc_id= A5;
const int xpin= A0;// x-axis
const int ypin= A1;// y-axis
const int zpin= A2; // z-axis
const int A = 0;
const int B = 1;
const int C = 2;
const int D = 3;
const int E = 4;
const int F = 5;
const int G = 6;
const int DP= 7;
const int First_num = 8;
const int Second_num= 9;
 
 
int led_gate = true; // LED灯异步锁 防止灯管乱闪
int wendu_gate = true; // 温度显示异步锁
 
int HistoryValue = 0;
int x_num;
int y_num;
int z_num;
int count;
 
int ledaaaa = 0;
 
 
const String XHEADER = "X: ";
const String YHEADER = "Y: ";
const String ZHEADER = "Z: ";
const String TAB = " ";
 
 
 
//初始化0~7管脚
void INIT(){
int i=0;
for(i;i<=9;i++){
digitalWrite(i, HIGH);
}
}
 
void first_close_all(){
int i=0;
for(i;i<=7;i++){
digitalWrite(i, HIGH);
}
}
 
void second_close_all(){
int i=0;
for(i;i<=7;i++){
digitalWrite(i, LOW);
}
}
//数字1
void num_one(){
digitalWrite(B, LOW);
digitalWrite(C, LOW);
}
//数字2
void num_two(){
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(G, LOW);
digitalWrite(E, LOW);
digitalWrite(D, LOW);
}
//数字3
void num_three(){
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(G, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}
//数字4
void num_four(){
digitalWrite(F, LOW);
digitalWrite(G, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
}
//数字5
void num_five(){
digitalWrite(A, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}
//数字6
void num_six(){
digitalWrite(A, LOW);
digitalWrite(F, LOW);
digitalWrite(E, LOW);
digitalWrite(D, LOW);
digitalWrite(C, LOW);
digitalWrite(G, LOW);
}
//数字7
void num_seven(){
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
}
//数字8
void num_eight(){
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
digitalWrite(E, LOW);
digitalWrite(F, LOW);
digitalWrite(G, LOW);
}
//数字9
void num_nine(){
digitalWrite(G, LOW);
digitalWrite(F, LOW);
digitalWrite(A, LOW);
digitalWrite(B, LOW);
digitalWrite(C, LOW);
digitalWrite(D, LOW);
}
//数字0
void num_zero(){
int i=0;
for(i;i<=5;i++){
digitalWrite(i, LOW);
}
}
 
// 显示数字
void display_first(int num){
INIT();
digitalWrite(First_num, HIGH);
digitalWrite(Second_num, LOW);
switch(num){
case 1:num_one();break;
case 2:num_two();break;
case 3:num_three();break;
case 4:num_four();break;
case 5:num_five();break;
case 6:num_six();break;
case 7:num_seven();break;
case 8:num_eight();break;
case 9:num_nine();break;
default:num_zero();break;
}
delay(1);
}
 
void display_second(int num){
INIT();
digitalWrite(First_num, LOW);
digitalWrite(Second_num, HIGH);
switch(num){
case 1:num_one();break;
case 2:num_two();break;
case 3:num_three();break;
case 4:num_four();break;
case 5:num_five();break;
case 6:num_six();break;
case 7:num_seven();break;
case 8:num_eight();break;
case 9:num_nine();break;
default:num_zero();break;
}
delay(1);
}
 
// LED 显示 异步
void *led(void *arg){
if(led_gate){
led_gate = false;
digitalWrite(12,HIGH);
digitalWrite(13,LOW);
delay(50);
digitalWrite(12,LOW);
digitalWrite(13,LOW);
led_gate = true;
}
return ((void *)0);
}
 
// 温度显示异步
void *display_temperature(void *arg)
{
if(wendu_gate){
wendu_gate = false;
int i;
int temperature = *(int *)arg;
if(temperature > 0 && temperature < 10){
for(i = 0;i<30;i++){
display_second(temperature);
delay(49);
}
}else if (temperature >=10 && temperature < 100){
int temperature_one = temperature / 10;
int temperature_two = temperature % 10;
for(i = 0;i<750;i++){
display_second(temperature_two);
display_first(temperature_one);
}
}
for(i = 0 ;i < 10 ; i++){
digitalWrite(i, LOW);
}
wendu_gate = true;
}
return ((void *)0);
}
 
void xyz(int temperature)
{
int tem_x,tem_y,tem_z;
tem_x = analogRead(xpin);
tem_y = analogRead(ypin);
tem_z = analogRead(zpin)/100;
printf("tem_x:%d ",tem_x);
printf("tem_y:%d ",tem_y);
printf("tem_z:%d ",tem_z);
if(abs(x_num - tem_x) > 3 || abs(y_num - tem_y) > 3 || abs(z_num - tem_z) > 3){
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_create(&thread, &attr, led, NULL);
pthread_create(&thread, &attr, display_temperature, &temperature);
pthread_attr_destroy(&attr);
}
count++;
printf("%d ",count);
printf("X : %d ",x_num);
printf("Y : %d ",y_num);
printf("Z : %d ",z_num);
x_num = tem_x;
y_num = tem_y;
z_num = tem_z;
}
 
void setup()
{
int i=0;
for(i;i<=9;i++){
pinMode(i,OUTPUT);
}
 
pinMode(12,OUTPUT);
pinMode(13,OUTPUT);
 
//设置波特率
x_num = analogRead(xpin);
y_num = analogRead(ypin);
z_num = analogRead(zpin)/100;
printf("X : %d ",x_num);
printf("Y : %d ",y_num);
printf("Z : %d ",z_num);
count = 0;
}
void loop()
{
int value;
float voltage;
float temperature;
float ftemperature;
value = analogRead(adc_id); // get adc value
 
HistoryValue = value;
// 将读数转换为电压,3.3v arduino使用3.3
voltage = value * 3.3;
voltage /= 4096.0;
 
// 现在输出温度
temperature = (voltage - 0.5) * 100 ;//从每度10 mv转换为500 mV偏移
//to degrees ((volatge - 500mV) times 100)
 
cout << "温度------------------"<< endl;
printf("%f degrees C ", temperature);
// 现在转换为华氏
ftemperature = (temperature * 9.0 / 5.0) + 32.0;
printf("%f degrees F ", ftemperature);
cout << "温度------------------"<< endl;
xyz(temperature/1);
//delay(300);
}

 

参考: linux下多线程的创建与等待详解