多线程-进程-开发板

首先对线程和进程进行一个简单概述:

在一些操作中,等待的时间是比较长的,为避免卡顿,或者反应不及时引入线程和进程,进程是资源分配的最小单位,线程是CPU调度的最小单位。为了便于理解,我们不妨做以下比喻,单进程单线程就像一个人在一个桌子上吃菜;单进程多线程就是多个人在同一个桌子上一起吃菜;多进程单线程则是多个人每个人在自己的桌子上吃菜。

1.多线程

.准备工作-安装

Ubuntu默认是没有pthread库的,需要安装,输入命令:

$ sudo apt-get install -y glibc-doc manpages-posix-dev
$ sudo apt-get install manpages-posix manpages-posix-dev

线程创建
pthread_create()可以创建线程,其代码如下:

void *thread_function(void *index)
e = pthread_create(
    pthread_t *thread_id,
    const pthread_attr_t *attr,
    thread_function,
    void *index
);

   注释: 1.thread_id 为所创建线程的id
               2.attr为线程的属性
               3.thread_function给所创建的线程附加内容
               4.index给thread_function函数提供所需要的参数
               值得注意的是,当线程创建成功时,其函数返回值为0,否则,为1。

线程终止

pthread_exit()可终止线程,其代码如下:

pthread_exit(void *retval)

注释:retval为线程的返回值,即退出码

线程连接
pthread_join()函数功能为等待指定线程结束,其放在主线程中目的是等待子线程结束,主线程再继续运行,其代码如下:

pthread_join(pthread_t thread, void **retval)

  

对属性对象进行初始化
pthread_attr_init()函数用于对线程属性对象的初始化,线程具有属性,在对该结构进行处理之前必须进行初始化,其代码如下:

int pthread_attr_init(pthread_attr_t *attr);

  注释:attr为线程属性结构体的指针变量

线程销毁

线程属性在使用之后就要对其进行销毁,即去初始化,要用到pthread_attr_destroy()函数,其代码如下:

int pthread_attr_destroy(pthread_attr_t *attr);

 互斥量、互斥锁
临界区:必须以互斥方式执行的代码段,即在临界区的范围内只能有一个活动的执行线程。

*互斥量(Mutex):又称为互斥锁,是用来保护临界区的特殊变量,每个互斥锁内部有一个线程等待队列,保存等待该互斥锁的线程。
*有锁定(locked)和解锁(unlocked)状态

*锁定状态:某个特定的线程正持有这个互斥锁,其他线程将阻塞在互斥锁的等待队列内;
*解锁状态,没有线程持有这个互斥锁,如果某个线程试图获取这个互斥锁,那么这个线程就可以得到这个互斥锁而不会阻塞。
 

互斥锁可用于使线程按顺序进行,其中互斥锁的初始化用到pthread_mutex_t mutex以及int pthread_mutex_init()函数,前者可静态初始化互斥锁,后者可动态初始化互斥锁其代码如下:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr);

注释:1.PTHREAD_MUTEX_INITIALIZER为一结构常量
           2.restrict mutex为新建的互斥锁变量
           3.restrict attr指定了新建互斥锁的属性

例子:

互斥锁的销毁

互斥锁的销毁意味着释放它所占用的资源,且要求锁当前处于开放状态。需要用到pthread_mutex_destroy()函数。由于在Linux中,互斥锁并不占用任何资源,pthread_mutex_destroy()除了检查锁状态以外没有其他动作。其代码如下:

int pthread_mutex_destroy(pthread_mutex_t *mutex);

如何对互斥锁进行“加锁”or“解锁”
互斥锁可用来保护多个线程共享的数据和结构不会被他人修改,一个互斥锁只能有两个状态,即加锁和解锁状态,所用到pthread_mutex_lock()和pthread_mutex_unlock()函数。加锁可使其不被其他线程访问,只能由一个线程掌握,解锁即解除加锁的互斥锁,而这所用到的代码如下:

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

注释:mutex为所要操作的互斥锁变量

死锁

这里通过让两个进程不断争夺运行资源来使程序进入死锁状态。

条件变量

#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
 
pthread_t tid_array[3];
int sum = 0;
pthread_mutex_t sum_lock = PTHREAD_MUTEX_INITIALIZER;   /* 互斥量 (静态初始化)*/
pthread_cond_t condition_sum_ready = PTHREAD_COND_INITIALIZER; 						/* 条件量 (静态初始化) */
 
void * worker_thread_func(void *arg) {
	int i;
	long id = (long) arg;
	for (i = 0; i < 60; i++) {
		pthread_mutex_lock(&sum_lock);                 /* 使用互斥量保护临界变量 */
		printf("t%ld: read sum value before = %d\n", id + 1, sum);
		sum++;
		printf("t%ld: read sum value after  = %d\n", id + 1, sum);
		pthread_mutex_unlock(&sum_lock);               /* 结束互斥量保护临界变量 */
		if (sum >= 100)
			pthread_cond_signal(&condition_sum_ready); 								 /* 通过条件量 发送条件通知 -> 唤醒等待线程 */
	}
	return NULL;
}
 
void * waiting_thread_func(void *arg) {
	long id = (long) arg;
	pthread_mutex_lock(&sum_lock);
	while (sum < 100) 																/* 不满足条件将一直等待 */
		pthread_cond_wait(&condition_sum_ready, &sum_lock);                         /* 通过条件量 等待条件通知 -> 唤醒等待线程 */
	sum = 0;
	printf("waiting_thread_func: clear sum value [我是等待线程,已被唤醒。 ]\n");
	printf("t%ld: read sum value = %d\n", id + 1, sum);
	pthread_mutex_unlock(&sum_lock);
	return NULL;
}
 
int main(void) {
	int err;
	long i;
	for (i = 0; i < 2; i++) {
		err = pthread_create(&(tid_array[i]), NULL, &worker_thread_func, (void *) i);         /* 创建线程 1 线程 2 */
		if (err != 0) {
			printf("Can't create thread :[%s]", strerror(err));
		}
	}
	
	err = pthread_create(&(tid_array[2]), NULL, &waiting_thread_func, (void *) i);            /* 创建线程 3 */
	if (err != 0)
		printf("Can't create thread :[%s]", strerror(err));
	for (i = 0; i < 3; i++)
		pthread_join(tid_array[i], NULL);
	
	return 0;
}

 2.进程

创建

进程的创建需要用到fork()函数,其作用是创建父子进程,且父子进程二者的进程号不一致,即二者分别走向不同的方向,互不干扰。且fork()函数的返回值有两个,第一个为父进程的进程号,第二个的返回值为0,是子进程返回的,若返回值为-1,则表明进程创建失败。

进程等待

进程等待用到wait()函数,进程一旦调用了wait()函数,该进程就会立刻阻塞,暂停运行,直至找到一个已经变为僵尸进程的子进程出现,wait()函数会收集这个子进程的信息,销毁后返回,都则会一直阻塞进程,其代码如下:

int wait(int* statloc);

注释:statloc用来保存被收集进程退出时的一些状态

守护进程

守护进程的创建需要用到daemon()函数,其独立于控制终端并且周期性地执行某种任务或等待 处理某些发生的事件,代码如下:

int daemon(int nochdir, int noclose);

当nochdir为0时,·函数会将进程的工作目录修改为根目录
    当noclose为0时,daemon将进程的输入输出以及错误输出都重定向到/dev/null文件夹下
编译各个程序并运行,解释工作状态及结果

进程的创建与终止

例子

/*  线程的创建与终止 :  */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
 
void *thread_function(void *index) { /* 线程函数 */
    long tid;
    tid = (long) index;
    printf("Hello World! This is thread #%ld!\n", tid); /* 打印线程对应的参数 */
    pthread_exit(NULL);    /* 退出线程 */
}
 
int main(int argc, char *argv[]) {
    pthread_t tid_array[NUM_THREADS];
    int returned_code_err;
    long index;
    for (index = 0; index < NUM_THREADS; index++) { /* 循环创建 5 个线程 */
        printf("In main: creating thread %ld.\n", index);
        returned_code_err = pthread_create(
            &tid_array[index],
            NULL,
            thread_function,
            (void *) index
        ); /* 创建线程 */
        if (returned_code_err) {
            printf("ERR: return code from pthread_create() is not 0, but %d\n", returned_code_err);
            exit(-1);
        }
    }
    printf("Main exits.\n");
    pthread_exit(NULL); /* 主线程退出 */
    return 0;
}

3.开发板

在安装完开发板以后打开

LCD图像和屏幕

分别输入下列命令打开LCD屏幕和图像

$ fb-test
$ ./myfb-test /dev/fb0

 串口EEPROM 

$ cd
$ i2cdetect -l #列出所有ic2总线
$ i2cdetect -y 0 #列出总线0上的设备

命令控制LED

安装LED驱动

$ cd
$ cd led_driver_qemu/
$ insmod 100ask_led.ko

 控制LED零号灯亮,控制LED一号灯灭

$ ./ledtest /dev/100ask_led0 on
$ ./ledtest /dev/100ask_led1 off

按键控制LED

$ cd
$ cd button_driver_qemu/
$ insmod button_drv.ko #扫描你的按键
$ insmod board_100ask_qemu_imx6ull.ko 

 启动按键控制

$ ./button_led_test

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值