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\n", (char*)arg, (uint_t)tid);

	pthread_mutex_lock( &mt );
	printf("I[tid=%u] am using, (*|^_^|*)\n", (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.\n", tid, counter);
	}
	printf("It is my[tid=%u] turn, so long i waited...msg=%s\n", tid, (char*)arg);
	pthread_mutex_unlock( &mt );
}

#define XX_CREATE_FAILED(err)		printf("create thread error : %s\n", 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

[email protected]:~/peteryfren/cpp/pthread> gcc -Wall -o pt_lock pt_lock.c -lpthread
[email protected]:~/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\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-gcc.exe --sysroot=D:\android-ndk-r9b-windows-x86\platforms\android-13\arch-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\toolchains\arm-linux-androideabi-4.6\prebuilt\windows\bin\arm-linux-androideabi-gcc.exe --sysroot=D:\android-ndk-r9b-windows-x86\platforms\android-13\arch-arm -pie -o pt_lock pt_lock.o

@pause

里面的gcc和android系统库路径须要依据机器上实际位置改动。

注意android上gcc编译与linux上有点点区别:ndk中gcc不须要须要显式指定-lpthread。可能pthread默认就会链接。

android-ndk-r9b-windows-x86\platforms\android-13\arch-arm\usr\lib文件夹下的这些so载入须要指定。。在Android.mk中类似。

命令行下执行run.cmd,编译pt_lock,然后推到手机上,注意我的nexus4必须是/data/local/tmp以下才有权限,执行后有错误,详细步骤:

E:\GitHub\ndk_tutorial\pthread_playground>adb shell
[email protected]:/ # cd /data/local/tmp
cd /data/local/tmp
[email protected]:/data/local/tmp # mv /sdcard/pt_lock ./
mv /sdcard/pt_lock ./
[email protected]:/data/local/tmp # chmod 751 pt_lock
chmod 751 pt_lock
[email protected]:/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. 生存者/消费者,读写。哲学家进餐模型

http://www.cs.nmsu.edu/~jcook/Tools/pthreads/examples.html

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

时间: 2024-12-26 16:17:16

linux和android端的pthread学习的相关文章

quick cocos2d x 手机(Android端)启动过程学习

简要学习下quick cocos2d x 在安卓端启动的过程. 首先需要了解一点:quick cocos2d x是依托于Android的activity和GLSurfaceView(继承自SurfaceView)的环境来显示quick层的游戏界面. (1)首先quick类的android游戏从AndroidManifest.xml文件指定的activity(假设AC)启动. (2)AC继承父类的Cocos2dxActivity. (3)调用静态初始化块,加载cocos2dx的动态库.也就是一些C

《Linux多线程服务端编程——使用muduo C++网络库》学习笔记

第一章 线程安全的对象生命期管理 第二章 线程同步精要 第三章 多线程服务器的适用场合与常用编程模型 第四章 C++多线程系统编程精要 1.(P84)11个常用的最基本Pthreads函数: 2个:线程的创建和等待结束(join).封装为muduo::Thread 4个:mutex的创建.销毁.加锁.解锁.封装为muduo::MutexLock 5个:条件变量的创建.销毁.等待.通知.广播.muduo::Condition 2.(P85)不推荐使用读写锁的原因是它往往造成提高性能的错觉(允许多个

Ionic3学习笔记(八)使iOS端、Android端 Navbar 透明化

本文为原创文章,转载请标明出处 若要使iOS端 Navbar 透明,只需要给 ion-navbar 添加 transparent 属性,但是Android端依旧会有一条border在,所以再给 ion-header 添加 no-border 属性 <ion-header no-border> <ion-navbar transparent> </ion-navbar> </ion-header> 如有不当之处,请予指正,谢谢-

C#程序员学习Android开发系列之学习路线图

通过前面的3篇博客已经简单的介绍了Android开发的过程并写了一个简单的demo,了解了Android开发的环境以及一些背景知识. 接下来这篇博客不打算继续学习Android开发的细节,先停一下,明确一下接下来的学习目标以及学习路线. 一.对Android开发的基本认识 1.Android原生开发是基于Java语言的,由于我比较擅长C#,所以对Java语言本身不太熟练,需要加强Java语言基础的练习,这一块我会穿插到具体的知识点练习当中,并且在必要的地方给出与C#语言的对比(其实基本上在语法层

Android(java)学习笔记160:Framework运行环境之启动Zygote

前面Android(java)学习笔记159提到Dalvik虚拟机启动初始化过程,就下来就是启动zygote进程: zygote进程是所有APK应用进程的父进程:每当执行一个Android应用程序,Zygote就会孵化一个子线程去执行该应用程序(系统内部执行dvz指令完成的)  Å特别注意:系统提供了一个app_process进程,它会自动启动ZygoteInit.java和SystemServer.java这两个类,app_process进程本质上是使用dalvikvm启动ZygoteInit

浅谈 unix, linux, ios, android 区别和联系

浅谈 unix, linux, ios, android 区别和联系 网上的答案并不是很好,便从网上整理的相对专业的问答,本人很菜,大佬勿喷 UNIX 和 Linux ??UNIX 操作系统(尤尼斯), 是一个强大的多用户.多任务操作系统,支持多种处理器架构,按照操作系统的分类,属于分时操作系统,最早由 KenThompson.Dennis Ritchie和Douglas McIlroy于1969年在AT&T的贝尔实验室开发.目前它的商标权由国际开放标准组织所拥有,只有符合单一UNIX 规范的

一起学Google Daydream VR开发,快速入门开发基础教程一:Android端开发环境配置一

原文因涉及翻墙信息,被强制删除,此文为补发! 准备工作 进入Google Daydream开发者官网,开启准备工作,官网地址:https://vr.google.com/daydream/developers/ -------------------------------------------------------------------------------------------------------------------- Google Daydream开发者网址: https

服务器安全运维:安全狗服云手机android端V2·2版正式上线

安全狗服云旗下基于云计算技术,于2014年初打造的云时代下最好的服务器安全运维云平台,其用"云安全,新运维"的思路为用户提供服务器安全所需的一切服务. 安全狗服云继7月9号服云web端V3.4(企业服务)版上线后,7月10号,服云android端V2·2版也正式上线.同web端V3.4一样,android端V2·2主要也是对企业服务功能模块进行全面的完善和升级,意在为企业用户带来更高效更便捷的安全服务.建议升级使用,地址:http://fuyun.safedog.cn/client.h

Android系统源码学习步骤

Android系统是基于Linux内核来开发的,在分析它在运行时库层的源代码时,我们会经常碰到诸如管道(pipe).套接字(socket)和虚拟文件系统(VFS)等知识. 此外,Android系统还在Linux内核中增加了一些专用的驱动程序,例如用于日志系统的Logger驱动程序.用于进程间通信的Binder驱动程序和用于辅助内存管理的匿名共享内存Ashmem驱动程序.在分析这些Android专用驱动程序的时候,也会碰到Linux内核中与进程.内存管理相关的数据结构. 因此,我们有必要掌握一些L