交叉编译
#include
#include
#include
/*thread1*/
void thread1(void)
{
int i = 0;
for(i = 0; i < 6; i++) {
printf("This is a pthread1. \n");
if(i == 2){
pthread_exit(0);
}
sleep(1);
}
}
/*thread2*/
void thread2(void)
{
int i;
for(i = 0; i < 3; i++){
printf("This is a pthread2. \n");
}
pthread_exit(0);
}
/*main*/
int main(void)
{
pthread_t id1, id2;
int i,ret;
/*create thread1*/
ret = pthread_create(&id1, NULL, (void *) thread1, NULL);
if(ret != 0){
printf("Create pthread1 error!\n");
exit(1);
}
/*create thread2*/
ret = pthread_create(&id2, NULL, (void *) thread2, NULL);
if(ret != 0) {
printf("Create pthread2 error!\n");
exit(1);
}
/*wait for thread to end*/
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
return 0;
}
执行
$CC thread_test.c
结果报错
出现编译错误undefined reference to ‘pthread_create’。由于pthread库不是标准linux库, 所以出错。 找不到函数库,通过静态调用,-lpthread,就可以编译通过
$CC thread_test.c -o thread_test.0 -lpthread
scp thread_test [email protected]:/tmp
#include
#include
#include
#include
/*thread1*/
void thread1(void)
{
int i = 0;
for(i = 0; i < 6; i++) {
printf("This is a pthread1. \n");
if(i == 2){
pthread_exit(0);
}
sleep(1);
}
}
/*thread2*/
void thread2(void)
{
int i;
while(1){
for(i = 0; i < 3; i++){
printf("This is a pthread2. \n");
sleep(1);
}
}
/* void pthread_exit(void *retval)
* Retval:pthread_exit()调用者线程的返回值,可由其他函数如pthread_join 来检索获取
*/
pthread_exit(0);
}
/*main*/
int main(void)
{
pthread_t id1, id2;
int i,ret;
pthread_attr_t attr;
/*初始化线程 */
pthread_attr_init(&attr);
/*设置线程绑定属性*/
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
/*设置线程分离属性*/
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
/* create thread1 创建线程
* int pthread_create ((pthread_t *thread, pthread_attr_t *attr,void *(*start_routine)(void *), void *arg))
* thread:线程标识符
* attr:线程属性设置
* start_routine:线程函数的起始地址
* arg:传递给start_routine的参数
* return:成功:0 出错:-1
*/
ret=pthread_create(&id1,&attr,(void *) thread1,NULL);
if(ret != 0){
printf("Create pthread1 error!\n");
exit(1);
}
/*create thread2*/
ret = pthread_create(&id2, NULL, (void *) thread2, NULL);
if(ret != 0) {
printf("Create pthread2 error!\n");
exit(1);
}
/*wait for thread to end*/
/* int pthread_join ((pthread_t th, void **thread_return))
* th:等待线程的标识符
* thread_return:用户定义的指针,用来存储被等待线程的返回值(不为NULL时)
* return:成功:0 出错:-1
*/
// pthread_join(id1, NULL); // pthread_join将当前线程挂起,等待线程的结束
pthread_join(id2, NULL);
// exit(0); // 所有线程都终止
return 0;
}
这次不放在嵌入式开发板上运行了,所以就用gcc编译了
gcc thread_test2.c -o thread_test2 -lpthread
直接在wsl中运行编译好的可执行文件thread_test2
因为有个while死循环的存在,所以程序就会一直运行下去,我们ctrl+c
来结束打印,然后输入free
使用“free”命令查看内存使用情况
这是程序运行之前的内存使用情况uesd
这是程序运行之后的内存使用情况used
/*
* 使用互斥锁来实现对变量lock_var 的加一、打印操作
*/
#include
#include
#include
#include
#include
#include
#include
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 创建快速互斥锁
int lock_var;
time_t end_time;
void pthread1(void *arg);
void pthread2(void *arg);
int main(int argc, char *argv[])
{
pthread_t id1,id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL) + 10;
/* 互斥锁初始化
* int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr)
* Mutex:互斥锁
* Mutexattr:PTHREAD_MUTEX_INITIALIZER:创建快速互斥锁;PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP:创建递归互斥锁;PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP:创建检错互斥锁
* return:成功:0 出错:-1
*/
pthread_mutex_init(&mutex, NULL);
/*创建两个线程*/
ret = pthread_create(&id1, NULL, (void *)pthread1, NULL);
if(ret != 0){
perror("pthread cread1");
}
ret = pthread_create(&id2, NULL, (void *)pthread2, NULL);
if(ret != 0){
perror("pthread cread2");
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}
void pthread1(void *arg)
{
int i;
while(time(NULL) < end_time){
/*
* int pthread_mutex_lock(pthread_mutex_t *mutex,)
int pthread_mutex_trylock(pthread_mutex_t *mutex,)
int pthread_mutex_unlock(pthread_mutex_t *mutex,)
int pthread_mutex_destroy(pthread_mutex_t *mutex,)
* Mutex:互斥锁
* return:成功:0 出错:-1
*/
/*互斥上锁*/
if(pthread_mutex_lock(&mutex) != 0){
perror("pthread_mutex_lock");
}else{
printf("pthread1:pthread1 lock the variable\n");
}
for(i = 0; i < 0; i++){
sleep(1);
lock_var++;
}
/*互斥锁解锁*/
if(pthread_mutex_unlock(&mutex) != 0){
perror("pthread_mutex_unlock\n");
}else{
printf("pthread1:pthread1 unlock the variable\n");
}
sleep(1);
}
}
void pthread2(void *arg)
{
int nolock = 0;
int ret;
while(time(NULL) < end_time){
/*测试互斥锁*/
ret = pthread_mutex_trylock(&mutex);
if(ret == EBUSY){
printf("pthread2:the variable is locked by pthread1\n");
}else{
if(ret != 0){
perror("pthread_mutex_trylock");
exit(1);
}else{
printf("pthread2:pthread2 got lock. The variable is %d\n", lock_var);
}
/*互斥锁解锁*/
if(pthread_mutex_unlock(&mutex) != 0){
perror("pthread_mutex_unlock");
}else{
printf("pthread2:pthread2 unlock the variable\n");
}
}
sleep(3);
}
}
代码是什么意思呢?
两个线程并发,线程一定时while循环,锁定时候线程二检测到上锁然后不运行服务函数,检测到解锁后运行服务函数输出
编译代码
使用同一个信号量sem,sem初始值设置为0,进程一执行P操作,sem-1=-1,所以该进程就将阻塞直到信号量sem大于等于0为止。
/*
* 信号量线程控制
*/
#include
#include
#include
#include
#include
#include
#include
#include
int lock_var;
time_t end_time;
sem_t sem;
void pthread1(void *arg);
void pthread2(void *arg);
int main(int argc, char *argv[])
{
pthread_t id1, id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL) + 30;
/*初始化信号量为1*/
ret = sem_init(&sem, 0, 1);
if(ret != 0){
perror("sem_init");
}
/*创建两个线程*/
ret = pthread_create(&id1, NULL, (void *)pthread1, NULL);
if(ret != 0){
perror("pthread cread1");
}
ret = pthread_create(&id2, NULL, (void *)pthread2, NULL);
if(ret != 0){
perror("pthread cread2");
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}
void pthread1(void *arg)
{
int i;
while(time(NULL) < end_time){
/*信号量减一,p操作*/
sem_wait(&sem);
for(i = 0; i < 2; i++){
sleep(1);
lock_var++;
printf("lock_var = %d\n", lock_var);
}
printf("pthread1:lock_var = %d\n", lock_var);
/*信号量加一,v操作*/
sem_post(&sem);
sleep(1);
}
}
void pthread2(void *arg)
{
int nolock = 0;
int ret;
while(time(NULL) < end_time){
/*信号量减一,p操作*/
sem_wait(&sem);
printf("pthread2:pthread1 got lock; lock_var = %d\n", lock_var);
/*信号量加一,v操作*/
sem_post(&sem);
sleep(3);
}
}
在输出的结果中,可以很清晰的看到,进程一执行了P操作后,线程二就被阻塞了不能执行,等待线程一执行完for循环过了2s之后,线程一执行V操作,sem=0,然后再等待一秒钟
sem现在大于等于0,所以该进程具有公共资源的访问权限,线程二可以执行V操作修改sem的值了,sem=-1,线程之间又发生了互斥,线程二执行输出,然后sleep 3秒钟。
/*
* 通过两个信号量来实现两个线程间的同步
* 程序先运行线程二,再运行线程一
*/
#include
#include
#include
#include
#include
#include
#include
int lock_var;
time_t end_time;
sem_t sem1, sem2;
void pthread1(void *arg);
void pthread2(void *arg);
int main(int argc, char *argv[])
{
pthread_t id1, id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL) + 30;
/*初始化两个信号量,一个信号量为1,一个信号量为0*/
ret = sem_init(&sem1, 0, 1);
ret = sem_init(&sem2, 0, 0);
if(ret != 0){
perror("sem_init");
}
/*创建两个线程*/
ret = pthread_create(&id1, NULL, (void *)pthread1, NULL);
if(ret != 0){
perror("pthread cread1");
}
ret = pthread_create(&id2, NULL, (void *)pthread2, NULL);
if(ret != 0){
perror("pthread cread2");
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}
void pthread1(void *arg)
{
int i;
while(time(NULL) < end_time){
/*P操作信号量sem2 = 0 信号量-1*/
sem_wait(&sem2);//现在sem2=-1,该线程阻塞,直到sem2的值大于等于零为止,也就是进程二执行V操作sem2=0
for(i = 0; i < 2; i++){
sleep(1);
lock_var++;
printf("lock_var = %d\n", lock_var);
}
printf("pthread1:lock_var = %d\n", lock_var);
/*V 操作信号量sem1 = 0 +1*/
sem_post(&sem1);//sem1 = 1
sleep(1);
}
}
void pthread2(void *arg)
{
int nolock = 0;
int ret;
while(time(NULL) < end_time){
/*P 操作信号量sem1 = 1 信号量-1*/
sem_wait(&sem1);//现在sem1=0 该线程具有公共资源的访问权限,执行
printf("pthread2:pthread1 got lock; lock_var = %d\n", lock_var);
/*V 操作信号量sem2 = -1 +1*/
sem_post(&sem2);//现在sem2=0,所以线程一就可以运行了
sleep(3);
}
}
从以下结果中可以看出,该程序确实实现了先运行线程二,再运行线程一。
对于线程一和线程二都在3s 的一个周期内进行并行的操作,因为有两个信号量,所以可以分别控制
在第一个时间中,sem2 = -1,sem1 = 0;所以线程二可以执行,线程一此时被阻塞, 需要等待sem2 >= 0 的状态。线程二执行了自己的输出pthread2:pthread1 got lock; lock_var = 0
,然后执行V操作,sem2 = 0,这时候线程一满足了执行的条件,执行设定的输出lock_var = 1
。这时候线程二也在运行,执行sleep(3),也就是延迟3s,只是这个过程没有了其他的输出。
在第二个时间中,因为满足了sem2 >= 0 的条件,所以继续执行lock_var = 2
,并且结束了for循环,执行输出pthread1:lock_var = 2
,而于此同时线程二依然在sleep中。
在第三个时间中,线程一执行了V操作,sem1 = 1,时间也来到了第三秒,一个时间周期完成。
/*
* 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲
区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时页必须等
待。
* 这里使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之
间的同步问题,mutex是用于这两个线程之间的互斥问题。其中avail初始化为N(有界缓冲
区的空单元数),mutex 初始化为1,full初始化为0。
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FIFO "myfifo"
#define N 5
int lock_var = 0;
int fd;
char buf_r[100];
sem_t mutex, full, avail;
time_t end_time;
void productor(void *arg);
void consumer(void *arg);
void pthread1(void *arg);
void pthread2(void *arg);
/*主函数*/
int main(int argc, char *argv[])
{
pthread_t id1, id2;
pthread_t mon_th_id;
int ret;
end_time = time(NULL) + 30;
/*创建有名管道*/
if((mkfifo(FIFO, O_CREAT|O_EXCL) < 0) && (errno != EEXIST)){
printf("cannot create fifoserver\n");
}
printf("Preparing for reading bytes...\n");
memset(buf_r, 0, sizeof(buf_r));
/*打开管道*/
fd = open(FIFO, O_RDWR|O_NONBLOCK, 0); // 新建文件myfifo
if(fd == -1){
perror("open");
exit(1);
}
/*初始化互斥信号量为1*/
ret = sem_init(&mutex, 0, 1);
/*初始化avail信号量为N*/
ret = sem_init(&avail, 0, N);
/*初始化full信号量为0*/
ret = sem_init(&full, 0, 0);
if(ret != 0){
perror("sem_init");
}
/*创建两个线程*/
ret = pthread_create(&id1, NULL, (void *)productor, NULL);
if(ret != 0){
perror("pthread cread1");
}
ret = pthread_create(&id2, NULL, (void *)consumer, NULL);
if(ret != 0){
perror("pthread cread2");
}
pthread_join(id1, NULL);
pthread_join(id2, NULL);
exit(0);
}
/*生产者线程*/
void productor(void *arg)
{
int i, nwrite;
while(time(NULL) < end_time){
/*P操作信号量avail和mutex*/
sem_wait(&avail); // avail= N-1
sem_wait(&mutex); // mutex= 1-1 =0
/*生产者写入数据*/
if((nwrite = write(fd, "hello", 5)) == -1){ // 字符数据“hello”写入到fd文件中
if(errno == EAGAIN){
printf("The FIFO has not been read yet. Please try later\n");
}
}else{
printf("write hello to the FIFO\n");
}
/*V操作信号量full和mutex*/
sem_post(&full); // full = -1+1 = 0 消费者线程可以运行了
sem_post(&mutex); // mutex = 0+1 = 1
sleep(1);
}
}
/*消费者线程*/
void consumer(void *arg)
{
int nolock = 0;
int ret, nread;
while(time(NULL) < end_time){
/*P操作信号量full和mutex*/
sem_wait(&full); // full = 0-1 = -1 阻塞等待生产者写入完成 full>=0
sem_wait(&mutex); // mutex = 1-1 = 0
memset(buf_r, 0, sizeof(buf_r)); // buf_r 置零
if((nread = read(fd, buf_r, 100)) == -1){ // 读取fd中消费者写入的数据到buf_r中
if(errno == EAGAIN){
printf("no data yet\n");
}
}
printf("read %s from FIFO\n", buf_r); // 输出buf_r
/*V操作信号量avail和mutex*/
sem_post(&avail); // avail = N
sem_post(&mutex); // mutex = 0+1 = 1
sleep(1);
}
}
编译之后执行,得到了预期的结果