利用pthread_create()写一个多线程程序并放到后台运行

本文通过使用pthread_create()函数创建多线程程序,并演示了多个线程同时修改全局变量可能导致的问题。介绍了如何运行和查看后台守护进程。

今天我们来利用pthread_create()函数来写一个多线程程序

#include <stdio.h>        
#include <pthread.h>
       
int    g_var = 0;                    /*定义全局变量*/
void *thread_worker1(void *arg)
{
    while(1)
    {
        printf("thread1 g_var=%d",++g_var);
        sleep(1);
    }
    return NULL;               /*函数指针返回NULL*/
}


void *thread_worker2(void *arg)
{  
     while(1)
     {
         printf("thread2 g_var=%d",++g_var);
         sleep(1);
     }
    return NULL;
 }


int main(int argc,char **argv)
{
    pthread_t tid1;                /*创建两个线程ID*/
    pthread_t tid2;


    pthread_create(&tid1,NULL,thread_worker1,"haha"); 
   
 /*pthread_create的四个参数分别为线程ID,线程属性默认NULL,执行函数名,传给该参数的参数*/
   
    printf("start thread_worker1[%lu]\n",tid1);    /*用%lu输出无符号长整型整数的线程ID*/


    pthread_create(&tid2,NULL,thread_worker2,"xixi");
    printf("start thread_worker2[%lu]\n",tid2);


    while(1)
    {
       printf("g_var=%d",++g_var);
        sleep(1);
    }


    return 0;
    
}

接下来我们看下它的执行结果,注意执行时添加链接-lpthread,没错,程序会像这样无休无止地运行下去,而且不管线程还是主程序,他们都在对一个全局变量g_var动手脚,而且执行时没有绝对的顺序之分,所以不上锁的话将会造成某些麻烦。我们以后也许会做到对上锁的介绍。

^[[A[lingyun@localhost file]$ gcc pthread-mutex.c -lpthread
[lingyun@localhost file]$ ./a.out                      
start thread_worker1[3077942128]
start thread_worker2[3067452272]
g_var=1
thread1 g_var=2
thread2 g_var=3
g_var=4
thread1 g_var=5
thread2 g_var=6
g_var=7
thread1 g_var=8
thread2 g_var=9
^C
[lingyun@localhost file]$ 

最后我们来简单介绍守护进程daemon(),用法为int daemon(int nochdir, int noclose),第一个参数为0时执行目录变为为根目录,否则不变,第二个参数为0时将标准输入、标准输出和标准出错都重定向到/dev/null,也就是把所有信息放进这个永远装不满的黑洞里,也不会打印到屏幕上,否则的话就是一如既往都不变。

也就是说,我们在程序中添入这样一段程序,就可以将其放入后台。

[lingyun@localhost file]$ gcc pthread-mutex.c -lpthread
[lingyun@localhost file]$ ./a.out                            
[lingyun@localhost file]$ ps aux | grep a.out                
lingyun  11414  0.0  0.0  22596   408 ?        Ssl  04:00   0:00 ./a.out
lingyun  11418  0.0  0.0   6052   784 pts/1    S+   04:00   0:00 grep a.out
[lingyun@localhost file]$ 

这样,它就被放在后台运行,我们可以轻松找到。



一.LED和蜂鸣器 注意: Linux驱动 扩展名.ko 的文件是Linux中编译好的驱动文件。 执行驱动文件的命令: insmod xxx.ko 如: insmod pwm.ko 安装蜂鸣器的驱动文件 insmod led_drv.ko 安装LED灯驱动文件 安装好了,在/dev/自动生成对应的设备文件 insmod pwm.ko ==》 /dev/pwm insmod led_drv.ko ===> /dev/led_drv PWM: step1: 装驱动(您开机之后,就需要安装这个驱动文件) insmod pwm.ko step2: 打开对应的驱动文件 int pwm_fd = open("/dev/pwm",O_RDWR); if(pwm_fd == -1) { } step3: 通过命令去控制蜂鸣器 unsigned char cmd = 1; //1---响 0 ----不响 write(pwm_fd,&cmd,1); unsigned char cmd = 0; //1---响 0 ----不响 write(pwm_fd,&cmd,1); step4: 关闭文件 LED: 依旧是四个步骤,跟上面的是一样的。 只有第三步操作有点区别: 通过命令去控制led灯 命令需要发送两个字节 第一个字节控制灯是亮还是灭 第二个字节选择控制那个led灯 D8-D10 cmd[0] = 1/0; cmd[1] = 8; //8 9 10 控制对应的哪一个灯 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 如果安装出现一下问题:insmod: can't insert 'pwm.ko': Device or resource busy 需要删除一个文件: 命令: rm /IOT/driver_ko/gec6818_beep.ko 然后重启: reboot 如果是这句话:insmod: can't insert 'pwm.ko': File exists 证明驱动已经安装完成,不需要管它。 示例代码: 二.线程 我们已经实现了 循环的图片播放,你被while陷入死循环中。 多线程并发 并发:同时能够执行两个或者两个以上的程序 //step1: 装驱动(您开机之后,就需要安装这个驱动文件) system("insmod pwm.ko"); // step2: 打开对应的驱动文件 int pwm_fd = open("/dev/pwm",O_RDWR); if(pwm_fd == -1) { perror("open pwm error\n"); return -1; } // step3: 通过命令去控制蜂鸣器 while (1) { unsigned char cmd = 1; //1---响 0 ----不响 write(pwm_fd,&cmd,1); sleep(1); cmd = 0; //1---响 0 ----不响 write(pwm_fd,&cmd,1); sleep(1); } // step4: 关闭文件 close(pwm_fd); 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 并发的实体:进程线程,任务 线程:是进程内部的指令的分支。多个线程就是多个指令序列,并发执 行。指令必须在函数内部,线程的指令部分也必须在函数内部。这个函 数,我们称为“线程函数”。 一个线程创建后,执行的指令全部保存在线程函数中。 这个线程函数执行完毕,线程的任务也就结束。 Linux中pthread的函数接口 main函数 ====> 主要线程线程执行完毕了,其他的线程就不能继续往下去执行了 线程函数:就是用来保存线程要完成的指令 线程函数: 返回值的类型:void * 函数的参数: void * 函数名: 见其知其意 eg: void * my_thread(void *) { //要去执行的一些指令 } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 创建一个线程pthread_create NAME pthread_create - create a new thread SYNOPSIS #include <pthread.h> int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg); @thread:线程的ID 线程的ID就是用pthread_t 这样的类来描述定义一个变量t1,用 来保存线程号,pthread_t t1; 在本函数参数是指针,指向你要保存的变量的 地址空间。 &t1 @attr:表示我们创建这个线程的属性,NULL,表示是采用默认 属性。 @start_routine:函数指针,指向我们要去执行的那一个线程 函数,线程函数的任务其实就是执行指向的那一个函数,所以我们之间把你要去执行 的那一个线程函数名作为参数传入即可。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 @arg:指向的空间中数据,将作为线程函数的参数传入,如果没 有参数就传NULL。 18 19 Compile and link with -pthread. 20 线程的退出: 1 NAME 2 pthread_detach - detach a thread 3 4 SYNOPSIS 5 #include <pthread.h> 6 7 int pthread_detach(pthread_t thread); 8 pthread_detach:用来把指定的线程设置为detach state属性。 9 当线程退出时,其他的资源就会被完全回收。 10 11 Compile and link with -pthread. 12 13 注意:试图分离一个已经处于分离状态的线程将会导致不确定的情况,应该尽量避免 此操作 14 一般的做法是在线程函数中调用这个函数 15 16 =====》 17 void *fun(void *arg) 18 { 19 pthread_detach(pthread_self()); //pthread_self()获取自 己的线程ID 20 } 示例: 1 #include <stdio.h> 2 #include <unistd.h> 3 #include <pthread.h> 4 5 //线程函数要执行的任务 6 void *my_thread(void *arg) 7 { 8 //要执行的任务、指令 9 while(1) 10 { 11 printf("Bye Bye\n"); 12 sleep(1); 13 } 14 return NULL; 15 } 16 17 18 int main() 19 { 20 //定义一个保存线程的ID的变量 21 pthread_t tid; 22 23 pthread_create(&tid,NULL,my_thread,NULL); 24 25 while (1) 26 { 27 printf("HEllo!!\n"); 28 sleep(1); 29 } 30 return 0; 31 32 } 任务:尝试在开发板上,设置一个退出按钮,点击就可以退出你们的循环相 册,给你们的上午的LED灯和蜂鸣器加装按钮。实现点击控制,用c语言给出代码,给出完整的代码,在开发板屏幕上显示按钮
最新发布
05-15
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜亚轲

你花钱的样子真帅

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值