线程的创建与终止
pthread_create()可以创建线程,其代码如下:
void *thread_function(void *index)
e = pthread_create(
pthread_t *thread_id,
const pthread_attr_t *attr,
thread_function,
void *index
);
线程的连接
pthread_join()函数功能为等待指定线程结束,其放在主线程中目的是等待子线程结束,主线程再继续运行,其代码如下:
pthread_join(pthread_t thread, void **retval)
属性对象的初始化与销毁
pthread_attr_init()函数用于对线程属性对象的初始化,线程具有属性,在对该结构进行处理之前必须进行初始化,其代码如下
int pthread_attr_init(pthread_attr_t *attr);
互斥锁静态与动态初始化及销毁
互斥锁可用于使线程按顺序进行,其中互斥锁的初始化用到pthread_mutex_t mutex以及int pthread_mutex_init()函数,前者可静态初始化互斥锁,后者可动态初始化互斥锁
PTHREAD_MUTEX_INITIALIZER为一结构常量
restrict mutex为新建的互斥锁变量
restrict attr指定了新建互斥锁的属性
互斥锁的销毁意味着释放它所占用的资源,且要求锁当前处于开放状态。需要用到pthread_mutex_destroy()函数
互斥锁加锁与解锁
互斥锁可用来保护多个线程共享的数据和结构不会被他人修改,一个互斥锁只能有两个状态,即加锁和解锁状态,所用到pthread_mutex_lock()和pthread_mutex_unlock()函数。加锁可使其不被其他线程访问,只能由一个线程掌握,解锁即解除加锁的互斥锁,而这所用到的代码如下:
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
进程的创建
进程的创建需要用到fork()函数,其作用是创建父子进程,且父子进程二者的进程号不一致,即二者分别走向不同的方向,互不干扰。且fork()函数的返回值有两个,第一个为父进程的进程号,第二个的返回值为0,是子进程返回的,若返回值为-1,则表明进程创建失败。
进程的等待
进程等待用到wait()函数,进程一旦调用了wait()函数,该进程就会立刻阻塞,暂停运行,直至找到一个已经变为僵尸进程的子进程出现,wait()函数会收集这个子进程的信息,销毁后返回,都则会一直阻塞进程,其代码如下:
int wait(int* statloc);
编译
/* 线程的创建与终止 : */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5void *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;
}
运行结果
S
./1. pthread_create_exit.out
In main: creating thread o.
In main: creating thread 1.
Hello World! This is thread #0!
In main: creating thread 2.
In main: creating thread 3
Hello World! This is thread #2!
In main: creating thread 4.
Main exits.
Hello World! This is thread #1!
Hello World! This is thread #3!
'Hello World! This is thread #4|
线程的连接
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define NUM_THREADS 4void *thread_func(void *index) { /* 线程函数 */
int i;
long tid;
double result=0.0;
tid = (long)index;
printf("Thread %ld starting...\n",tid);for (i=0; i<1000000; i++) {
result = result + sin(i) * tan(i); /* 进行数学运算 */
}
printf("Thread %ld done. Result = %e\n",tid, result);
pthread_exit((void*) index); /* 带计算结果退出 */
}
int main (int argc, char *argv[]) {
pthread_t tid_array[NUM_THREADS];
int err;
long index;
void *status;for(index=0; index<NUM_THREADS; index++) {
printf("Main: creating tid_array %ld\n", index);
err = pthread_create(
&tid_array[index],
NULL,
thread_func,
(void *)index
); /* 创建线程 */
if (err) {
printf("ERROR; return code from pthread_create() is %d\n", err);
exit(-1);
}
}for(index=0; index<NUM_THREADS; index++) {
err = pthread_join(
tid_array[index],
&status
); /*等待线程终止,并获取返回值*/
if (err) {
printf("ERROR; return code from pthread_join() is %d\n", err);
exit(-1);
}
printf("Main: completed join with tid_array %ld having a status of %ld\n",index,(long)status);
}printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
属性对象的初始化与销毁
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>#define handle_error_en(en, msg) do {errno = en; perror(msg); exit(EXIT_FAILURE);}while (0)
#define handle_error(msg) do {perror(msg); exit(EXIT_FAILURE);}while (0)struct thread_info {
pthread_t thread_id;
int thread_num;
char *argv_string;
};static void *thread_func(void *arg) { /* 线程运行函数 */
struct thread_info *thread_info_struct_array = arg;
char *uargv, *p;
printf("Thread %d: top of stack near %p; argv_string=%s\n", /* 通过 p 的地址来计算栈的起始地址*/
thread_info_struct_array->thread_num, &p, thread_info_struct_array->argv_string);uargv = strdup(thread_info_struct_array->argv_string);
if (uargv == NULL)
handle_error("strdup");
for (p = uargv; *p != '\0'; p++)
*p = toupper(*p); /* 小写字符转换大写字符 */return uargv; /* 将转换结果返回 */
}int main(int argc, char *argv[]) {
int s, index, opt, num_threads;
struct thread_info *thread_info_struct_array;
pthread_attr_t attr_struct;
int stack_size;
void *res;
stack_size = -1;/* 处理参数 -s 所指定的栈大小 */
while ((opt = getopt(argc, argv, "s:")) != -1) {
switch (opt) {
case 's':
stack_size = strtoul(optarg, NULL, 0); // string to unsigned long
break;
default:
fprintf(stderr, "Usage: %s [-s stack-size] arg...\n", argv[0]);
exit(EXIT_FAILURE);
}
}num_threads = argc - optind;
/* 初始化属性对象 */
s = pthread_attr_init(&attr_struct);
if (s != 0)
handle_error_en(s, "pthread_attr_init");if (stack_size > 0) {
/* 设置属性对象的栈大小 为 用户命令行参数 -s 指定值 */
s = pthread_attr_setstacksize(
&attr_struct,
stack_size
);
if (s != 0)
handle_error_en(s, "pthread_attr_setstacksize");
}
thread_info_struct_array = calloc(num_threads, sizeof(struct thread_info));if (thread_info_struct_array == NULL)
handle_error("calloc");for (index = 0; index < num_threads; index++) {
thread_info_struct_array[index].thread_num = index + 1;
thread_info_struct_array[index].argv_string = argv[optind + index];
s = pthread_create(
&thread_info_struct_array[index].thread_id,
&attr_struct, /* 根据属性创建线程 */
&thread_func,
&thread_info_struct_array[index]
);
if (s != 0)
handle_error_en(s, "pthread_create");
}/* 销毁属性对象 */
s = pthread_attr_destroy(&attr_struct);
if (s != 0)
handle_error_en(s, "pthread_attr_destroy");for (index = 0; index < num_threads; index++) {
s = pthread_join(thread_info_struct_array[index].thread_id, &res); /* 等待线程终止,并获取返回值 */
if (s != 0)
handle_error_en(s, "pthread_join");printf("Joined with thread %d; returned value was %s\n",
thread_info_struct_array[index].thread_num, (char *) res);
free(res);
}free(thread_info_struct_array);
exit(EXIT_SUCCESS);
}
条件变量
#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;
}
运行开发板
~/ubuntu-18.04_imx6ul_qemu_system/gui-qemu-imx6ull-gui.sh
使用开发板
fb-test
myfb-test /dev/fb0
命令控制LED
cd ~/led_driver_qemu/
insmod 100ask_led.ko
./ledtest /dev/100ask_led0 on
./ledtest /dev/100ask_led1 on
./ledtest /dev/100ask_led2 on
按键控制LED
cd ~/button_driver_qemu/
insmod button_drv.ko
insmod board_100ask_qemu_imx6u
./button_led_test