C 语言 pthread.h 实现启动线程; 基于MacOSX + CLion

版权声明:本文为匆忙拥挤repeat(stone)原创文章,转载请注明出处 —— http://blog.csdn.net/jjwwmlp456 https://blog.csdn.net/jjwwmlp456/article/details/89345922

文章目录


前言

不同的操作系统,对于 C 语言 标准库,可能有不同的实现。(查资料说是,unix 系统是标准的实现了POSIX,linux 系统是非标准的。反正,我是晕乎乎的) 有些在 linux 上能访问的头文件,在 mac osx (基于unix 的) 上,就无法访问。

我的需求:
我干安卓的,期望 c 程序运行在 安卓的 linux 虚拟机上。
然后,下了个 CLion ,来学习下 C 的线程实现。
然后就遇到了:使用标准库 <time.h>有问题,需要使用 <unistd.h> ,才能使用线程睡眠函数 sleep() …
郁闷、折腾了好久…
还遇到了:写个控制台程序,用 pthread 创建了线程,子线程内还没执行完呢,主线程已经结束了,子线程也就结束了 …
最后,想正常的退出线程。


案例

用 CLion 建立了一个 c++ 可执行工程。
新建两个文件
PthreadTest1.c PthreadTest1.h

由于程序入口是 main.cpp,要链接 c 的源文件,所以要用extern "C" {}; 注意后一个大括号后面还有个分号,因为刚开始没写它,造成编译错误,根本看不懂哪错了,哭死我了…

PthreadTest1.h :

#ifndef UNTITLED1_PTHREADTEST1_H
#define UNTITLED1_PTHREADTEST1_H


#ifdef __cplusplus
extern "C" {
#endif

extern int flag; //全局变量,不可初始化
void threadRun1(); 

#ifdef __cplusplus
};
#endif

#endif //UNTITLED1_PTHREADTEST1_H

PthreadTest1.c

#include "PthreadTest1.h"
#include <unistd.h> //macos : sleep()、usleep()
#include <pthread.h>
#include <stdio.h>  //printf()

int flag = 1; //初始化全局变量
 //函数声明提前,以使后面能调用;具体实现在最后
 // c 语言中,要想调用一个函数,必须在当前函数之前就声明好了;可以先声明好,后续再实现它
 //用于线程操作的函数,返回值和参数 最好就如此定义
void* test1(void* arg);

void threadRun1() {
	pthread_t pid;
	//若创建线程成功则返回0,否则返回出错编号
	//这里传了一个   &pid 的参数给到 函数 test1
    int res = pthread_create(&pid, NULL, test1, &pid);
    printf("res=%d,%s\n", res, !res?"创建成功":"创建失败");
	
	int rv; 
	//等待 pid 线程执行完;第二个参数用于接收,线程函数的返回值或 pthread_exit(rv) 中的 rv 值
    pthread_join(pid, (void **) &rv);

	printf("the thread id:%lu exit:%d\n", pid, rv);
}

void* test1(void* arg) {
    //获取参数
    pthread_t* pid = arg;
	int c = 0;
    while (flag) {
    	printf("c=%d ", c++);
    	// usleep(1000*1000); // 1 second
    	sleep(1);//1 second
		
		//线程退出 1
		//if (c > 5) {
        //  return 1001;   //join-rv = 1001;
        //}
		
		//正常退出循环,会执行到 线程退出3
		if (c > 5) {
            flag = 0;
            //break;  //与 flag = 0  效果一样的
        }
		
		//线程退出 2
		if (c > 2) {
            int rv = 1002;
            printf("pid: %lu\n", *pid);
            pthread_exit((void *) rv);
        }
    }
	
	//return NULL;   //就相当于 retun 0	

	//线程退出 3
	//int rv = 1003;
    //printf("pid:  %lu\n", *pid);
    //pthread_exit((void *) rv);
}

main.cpp

#include "PthreadTest1.h"
int main() {

//    flag = 0;  //这个打开了,线程函数内的循环就不执行了
    threadRun1();

    return 0;
}

pthread_create() 创建线程并立即执行。
pthread_join()等待指定线程执行结束。由于调用者是主线程,所以主线程被阻塞了,会等待子线程执行完;就不会出现主线程一结束,子线程也结束了的情况。第二个参数还可以接收: 线程函数的返回值或 pthread_exit(rv) 中的 rv 值。
pthread_exit(void* returnValue) 线程退出。 并传递一个返回值参数,给到 pthread_join()中的第二个参数。即线程函数不同的退出方式,可以发不同的消息出去。

本例测试时,在线程函数 test1()中, 可以对 “线程退出 1、2、3” 相关语句块,注释掉其中2个,保留一个后进行测试。

本例中 unistd.h ,如果在测试时发现它找不到,那就换成 time.h试试 。


后记

权当学习记录下吧,实现了有限的几个函数的有效调用。

其它一些 线程函数, pthread_cancel、pthread_kill 等等,以为有多好使,测试后现,实在太难用了,用不出期望的效果…
感觉可能还是用 c++来实现多线程比较好,c11后有<thread>这个标准库。
安卓上,通常也是建议用 c++实现的,c 只是用于混编的,或调用三方库,真要完全基于 c 来实现自己的需求,估计要玩死人…


猜你喜欢

转载自blog.csdn.net/jjwwmlp456/article/details/89345922