zoukankan      html  css  js  c++  java
  • linux和android端的pthread学习

    本文起初主要想写个演示样例实測下pthread_mutex_lock和pthread_mutex_trylock差别。在linux机器上非常快就over了,可是想了一下。pthread是unix系的,在windows没办法直接执行代码非常不方便。于是想到了android,windows上安装ndk,手机root就能够跑pthread代码咯。。。

    demo

    lock和trylock的差别也非常好理解:,前者是堵塞的。死等知道相互排斥锁被释放;而后者则更加灵活。浅尝辄止。做个尝试不行则干其它事情去。。測试代码pt_lock.c例如以下:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <sys/types.h>
    
    typedef pthread_t pt_t;
    typedef unsigned int uint_t;
    
    pthread_mutex_t mt = PTHREAD_MUTEX_INITIALIZER;
    
    void lock_func(void* arg)
    {
    	pid_t pid;	//process
    	pt_t tid;	// thread
    	
    	pid = getpid();
    	tid = pthread_self();
    
    	printf("want to lock mutex, msg=%s, tid=%u
    ", (char*)arg, (uint_t)tid);
    	
    	pthread_mutex_lock( &mt );
    	printf("I[tid=%u] am using, (*|^_^|*)
    ", (uint_t)tid);
    	sleep(10);
    	pthread_mutex_unlock( &mt );
    }
    
    void try_lock_func(void* arg)
    {
    	uint_t tid = (uint_t)pthread_self();
    	int counter = 0;
    	
    	while ( pthread_mutex_trylock( &mt ) )
    	{
    		sleep(1);
    		++counter;
    		
    		printf("after sleep 1s, i [tid=%u] want to try again, iter=%d.
    ", tid, counter);
    	}
    	printf("It is my[tid=%u] turn, so long i waited...msg=%s
    ", tid, (char*)arg);
    	pthread_mutex_unlock( &mt );	
    }
    
    #define XX_CREATE_FAILED(err)	
    	printf("create thread error : %s
    ", strerror(err));
    	return 1;	
    
    int main()
    {
    	int rc;
    	pt_t pt1, pt2, pt3;
    	
    	const char* msg1 = "block";
    	const char* msg2 = "unblock";
    	
    	rc = pthread_create(&pt1, NULL, (void*)&lock_func, (void*)msg1);	if (rc != 0) 
    	{
    		XX_CREATE_FAILED(rc);
    	}
    	
    	rc = pthread_create(&pt2, NULL, (void*)&lock_func, (void*)msg1);	if (rc != 0)
    	{
    		XX_CREATE_FAILED(rc);
    	}
    	sleep(1);
    	
    	rc = pthread_create(&pt3, NULL, (void*)&try_lock_func, (void*)msg2);	if (rc != 0)
    	{
    		XX_CREATE_FAILED(rc);
    	}
    	
    	pthread_join(pt1, NULL);
    	pthread_join(pt2, NULL);
    	pthread_join(pt3, NULL);	
    	return 0;
    }
    
    代码思路也非常好理解:创建三个线程。1和2通过lock方式去争抢mt相互排斥锁,3线程则灵活,每隔1秒去检測下mt相互排斥锁能否够用,不会堵塞。

    线程1或者2占有mt的时间为10秒。


    linux run

    xx@h10-1-152-72:~/peteryfren/cpp/pthread> gcc -Wall -o pt_lock pt_lock.c -lpthread
    xx@h10-1-152-72:~/peteryfren/cpp/pthread> ./pt_lock 
    输出结果与预期一致,id=1082132800线程先占有mt。10s内线程tid=1090525504堵塞,而线程tid=1098918208每隔1s測试下mt可用性。
    want to lock mutex, msg=block, tid=1082132800
    I[tid=1082132800] am using, (*|^_^|*)
    want to lock mutex, msg=block, tid=1090525504
    after sleep 1s, i [tid=1098918208] want to try again, iter=1.
    after sleep 1s, i [tid=1098918208] want to try again, iter=2.
    after sleep 1s, i [tid=1098918208] want to try again, iter=3.
    after sleep 1s, i [tid=1098918208] want to try again, iter=4.
    after sleep 1s, i [tid=1098918208] want to try again, iter=5.
    after sleep 1s, i [tid=1098918208] want to try again, iter=6.
    after sleep 1s, i [tid=1098918208] want to try again, iter=7.
    after sleep 1s, i [tid=1098918208] want to try again, iter=8.
    I[tid=1090525504] am using, (*|^_^|*)
    after sleep 1s, i [tid=1098918208] want to try again, iter=9.
    after sleep 1s, i [tid=1098918208] want to try again, iter=10.
    after sleep 1s, i [tid=1098918208] want to try again, iter=11.
    after sleep 1s, i [tid=1098918208] want to try again, iter=12.
    after sleep 1s, i [tid=1098918208] want to try again, iter=13.
    after sleep 1s, i [tid=1098918208] want to try again, iter=14.
    after sleep 1s, i [tid=1098918208] want to try again, iter=15.
    after sleep 1s, i [tid=1098918208] want to try again, iter=16.
    after sleep 1s, i [tid=1098918208] want to try again, iter=17.
    after sleep 1s, i [tid=1098918208] want to try again, iter=18.
    after sleep 1s, i [tid=1098918208] want to try again, iter=19.
    It is my[tid=1098918208] turn, so long i waited...msg=unblock

    android run

    android上编译和执行pt_lock參考前一篇blog:http://blog.csdn.net/ryfdizuo/article/details/28891649   详细批处理run.cmd例如以下:
    @echo "1. build .o file"
    
    @Rem fPIE flag is used in compiling stage.
    D:android-ndk-r9b-windows-x86	oolchainsarm-linux-androideabi-4.6prebuiltwindowsinarm-linux-androideabi-gcc.exe --sysroot=D:android-ndk-r9b-windows-x86platformsandroid-13arch-arm -fPIE -c pt_lock.c
    
    @echo "2. build exec file"
    
    @Rem pie flag is used in linking stage.
    D:android-ndk-r9b-windows-x86	oolchainsarm-linux-androideabi-4.6prebuiltwindowsinarm-linux-androideabi-gcc.exe --sysroot=D:android-ndk-r9b-windows-x86platformsandroid-13arch-arm -pie -o pt_lock pt_lock.o
    
    @pause
    
    里面的gcc和android系统库路径须要依据机器上实际位置改动。
    注意android上gcc编译与linux上有点点区别:ndk中gcc不须要须要显式指定-lpthread。可能pthread默认就会链接。

    android-ndk-r9b-windows-x86platformsandroid-13arch-armusrlib文件夹下的这些so载入须要指定。。在Android.mk中类似。

    命令行下执行run.cmd,编译pt_lock,然后推到手机上,注意我的nexus4必须是/data/local/tmp以下才有权限,执行后有错误,详细步骤:
    E:GitHub
    dk_tutorialpthread_playground>adb shell
    root@mako:/ # cd /data/local/tmp
    cd /data/local/tmp
    root@mako:/data/local/tmp # mv /sdcard/pt_lock ./
    mv /sdcard/pt_lock ./
    root@mako:/data/local/tmp # chmod 751 pt_lock
    chmod 751 pt_lock
    root@mako:/data/local/tmp # ./pt_lock
    error: only position independent executables (PIE) are supported.
    报了PIE不支持的错误,n4上安装的是android L系统。gg后知道编译的链接的须要添加pie等设置,參见[ref2],fPIE是编译时候的选项,pie是链接时候的选项。再次又一次编译,推到手机上执行OK。。。pt_lock.c不须要做不论什么改动。

    pthread学习

    1.线程相关
    1)回调函数类型 void* (*pfunc) (void* arg) 。參数通过void*传入,多个參数是通过结构体/数组打包。
    2)线程属性,能够设置线程类型,通常是joinable。设置线程栈的大小。假设线程内部要定义大数组一定小心栈越界。

    3)线程终止的几种情况:
    • 回调函数执行完毕。正常退出
    • 线程内调用pthread_exit函数。无论是否完毕都退出。该函数后面的全部代码都不会被执行(尤其printf等语句)。
    • 其它线程显式调用pthread_cancel 结束当前线程。
    • 整个进程被终止,由于调用了exit等函数。它以下的全部线程都被杀死。资源被回收。

    • main函数创建N个线程。两种做法等待其它线程结束:显式pthread_join等待其它线程结束;main函数中调用pthread_exit,等待其它线程结束。

    2. 相互排斥锁相关
    pthread_mutex_init
    pthread_mutex_lock。堵塞等待
    pthread_mutex_trylock,非堵塞等待
    pthread_mutex_destroy

    3. 信号量相关
    pthread_mutex_init
    pthread_mutex_wait 堵塞当前线程,直到满足某些条件时。伪代码例如以下:
    begin
    pthread_mutex_unlock( mutex )  堵塞之前释放相互排斥锁
    block_on_cond( condition ) 条件堵塞
    pthread_mutex_lock(mutex) 条件满足后 占有相互排斥锁,完毕工作后须要释放相互排斥锁
    end
    该语句必须在循环中运行,而不是if中,由于线程之间可能有虚假的唤醒行为,spurious wakeup。当唤醒时须要再次确定预期的条件是否满足。假设不满足继续等待。

    相关的讨论參见:http://a-shi.org/blog/2012/07/27/pthread_cond_wait_mutex_while/


    pthread_mutex_signal,仅仅有一个线程等待时发送信号量
    pthread_mutex_broadcast 多个线程同一时候等待时使用
    pthread_mutex_destroy

    4. 生存者/消费者,读写。哲学家进餐模型

    refer

    1. gcc以下的pie和fPIE 选项标志解说,http://richardustc.github.io/blog/2013/05/pie/

    2. android L系统下PIE错误,http://blog.csdn.net/hxdanya/article/details/39371759

    3. pthread http://man7.org/linux/man-pages/man3/pthread_create.3.html


  • 相关阅读:
    excel套模板
    随便写写
    Ajax请求本页
    解除默认asp.net 上传文件大小的限制
    客户端获取mac ip 主机名
    获取客户端Mac
    vue中使用swiper出现Can't resolve 'swiper/dist/css/swiper.css'
    win10 输入法小技巧
    VS Code 编辑器配置备份
    axios报错: Cannot read property 'protocol' of undefined ....
  • 原文地址:https://www.cnblogs.com/wzzkaifa/p/7281800.html
Copyright © 2011-2022 走看看