多线程、进程、开发版

1 多线程

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

1.1安装

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

安装完成后,我们进行代码测试演示

1.2 创建线程

#include 
int pthread_create(
                 pthread_t *restrict tidp,   //新创建的线程ID指向的内存单元。
                 const pthread_attr_t *restrict attr,  //线程属性,默认为NULL
                 void *(*start_rtn)(void *), //新创建的线程从start_rtn函数的地址开始运行
                 void *restrict arg //默认为NULL。若上述函数需要参数,将参数放入结构中并将地址作为arg传入。
                  );

多线程、进程、开发版_第1张图片

 首先我们需要makeflie把所有的.c文件编译一下,接下来我们运行程序,输入命令:

$ ./1.pthread_create_exit.out

多线程、进程、开发版_第2张图片

我们可以看到使用pthread_create创建了五个线程并显示出来,用pthread_exit来终止线程。 

1.2 终止线程

函数原型:

void pthread_exit(void*_retval)

1.3 线程连接

函数原型:

int pthread_join(
               pthread_t tid, //需要等待的线程,指定的线程必须位于当前的进程中,而且不得是分离线程
               void **status  //线程tid所执行的函数返回值(返回值地址需要保证有效),其中status可以为NULL
                 );

多线程、进程、开发版_第3张图片

多线程、进程、开发版_第4张图片 这里我们可以看一下函数代码,接下来我们运行程序,输入命令

$ ./2.pthread_join.out

 多线程、进程、开发版_第5张图片

1.4使用互斥量保护多线程同时输出

初始化互斥锁

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutex_attr_t *mutexattr);

mutex表示的是互斥锁的标号; mutexattr表示的互斥锁的属性,一般情况使用NULL,表示缺省属性。 成功返回0 失败返回错误号

上锁

int pthread_mutex_lock(pthread_mutex_t *mutex);’

解锁

int pthread_mutex_unlock(pthread_mutex_t *mutex);'

示例如下

多线程、进程、开发版_第6张图片

 运行结果如下

多线程、进程、开发版_第7张图片

我们可以看到使用互斥锁可以同一时间内只有一个线程访问数据。

1.5 死锁 

多线程、进程、开发版_第8张图片

多线程、进程、开发版_第9张图片

所谓死锁就是让两个进程不断争夺运行资源来使程序进入死锁状态。然后我们运行程序,输入命令

$ ./5.pthread_dead_lock_of_mutex.out

1.6 条件变量 

多线程、进程、开发版_第10张图片

多线程、进程、开发版_第11张图片

$ ./6.pthread_conditional_var.out

 多线程、进程、开发版_第12张图片

2 进程

2.1 进程简介

狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。
广义定义:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
Linux 的进程有以下6种状态:
D:不可中断的深度睡眠状态,处于这种状态的进程不能响应异步信号;
R:进程处于运行态或就绪状态,只有在该状态的进程才可能在CPU上运行。而同一时刻可能有多个进程处于可执行状态;
S:可中断的睡眠状态,处于这个状态的进程因为等待某种事件的发生而被挂起。;
T:暂停状态或跟踪状态;
X:退出状态,进程即将被销毁;
Z:退出状态,进程成为僵尸进程。

2.2 获取环境变量

获取环境变量的方式:
多线程、进程、开发版_第13张图片

多线程、进程、开发版_第14张图片

2.3 创建进程

函数以拷贝父进程的方式创建子进程。子进程与父进程有相同的代码空间、文件描述符等资源
创建后,子进程与父进程开始并发执行,执行顺序由内核调度算法来决定
fork()对父子进程各返回一次,
父进程:子进程的PID,
子进程:0;
失败: 小于0;
同样运行.c 文件前我们需要makefile
多线程、进程、开发版_第15张图片

运行结果

$ ./3-fork-print-pid.out

 

2.4守护进程

守护进程是脱离于终端并且在后台运行,周期性的执行某种任务或者等待处理某些发生的事件进程。

使用‘daemon()’创建守护进程

 运行结果如下

多线程、进程、开发版_第16张图片

2.5信号函数sigaction的使用

信号函数用来通知进程发生了异步事件

函数结构

struct sigaction {
    void (*sa_handler)(int);
    void (*sa_sigaction)(int, siginfo_t *, void *);
    sigset_t sa_mask;
    int sa_flags;
    void (*sa_restorer)(void);
	}

示例

多线程、进程、开发版_第17张图片

运行结果如下图

多线程、进程、开发版_第18张图片

2.6 子进程:等待、退出及输出 

多线程、进程、开发版_第19张图片

子进程经过两次等待,父进程将信号传给子进程后,通过exit()退出,并且输出子进程的退出状态 

 2.7 管道

管道,即进程间数据流的通道。通常A进程输出连B进程输入端。符号“|"
1.匿名管道: pipe文件
函数原型:

int pipe(int pipefd[2])

2.命名管道: fifo文件:int mkfifo(const char *pathname, mode_t mode)(ps:参数pathname指定了文件名
参数mode则指定了文件的读写权限)
多线程、进程、开发版_第20张图片

2.8 通过命名管道发送文件

函数

多线程、进程、开发版_第21张图片

 2.9 共享内存读数据

多线程、进程、开发版_第22张图片

多线程、进程、开发版_第23张图片

多线程、进程、开发版_第24张图片

3.开发板

3.1 下载、安装、运行QEMU

下载成功后,进入ubuntu-18.04_imx6ul_qemu_system目录,执行install_sdl.sh

必须在Ubunut的桌面环境下启动终端,执行./qemu-imx6ull-gui.sh
我们可以看到下面界面

3.2 打开LCD图像和屏幕

$ fb-test
$ cd myfb-test

多线程、进程、开发版_第25张图片

$ ./myfb-test /dev/fb0

多线程、进程、开发版_第26张图片

 3.3 串口EEPROM

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

UU:有设备,有内核驱动
地址:有设备,无驱动

多线程、进程、开发版_第27张图片

矩阵的最左列是十位,最上面是个位。

3.4 命令控制LED

安装LED驱动

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

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

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

多线程、进程、开发版_第28张图片

3.5 按键控制LED

安装驱动

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

 启动按键控制

$ ./button_led_test

多线程、进程、开发版_第29张图片

 参考:https://blog.csdn.net/Zeilo/article/details/124084107?spm=1001.2014.3001.5502

你可能感兴趣的:(ubuntu)