0
点赞
收藏
分享

微信扫一扫

多进程-进程-开发板

水沐由之 2022-04-14 阅读 81
linux

一. 多线程

1.1 安装

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

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

1.2 创建线程

#include <pthread.h>
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传入。);

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

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

$ ./1.pthread_create_exit.out

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 使用pthread_create创建了五个线程并显示出来,用pthread_exit来终止线程。

1.3 终止线程

void pthread_exit(void*_retval)

1.4 线程连接

int pthread_join(

               pthread_t tid, //需要等待的线程,指定的线程必须位于当前的进程中,而且不得是分离线程

               void **status //线程tid所执行的函数返回值(返回值地址需要保证有效),其中status可以为NULL  );

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 1.5 线程管理

1.5.1 线程初始化

int pthread_attr_init(pthread_attr_t *attr);
1.5.2 线程销毁

int pthread_attr_destroy(pthread_attr_t *attr);

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16 

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

1.6 死锁

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16 

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

 

$ ./5.pthread_dead_lock_of_mutex.out

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 我们可以看到程序进入死锁状态,我们使用ctrl+z退出死锁。

1.7条件变量

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16 同样输入指令运行程序:

$ ./6.pthread_conditional_var.out

运行结果如下

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

二、进程

2.1 简介

Linux 的进程有以下6种状态:

D:不可中断的深度睡眠状态,处于这种状态的进程不能响应异步信号;

R:进程处于运行态或就绪状态,只有在该状态的进程才可能在CPU上运行。而同一时刻可能有多个进程处于可执行状态;

S:可中断的睡眠状态,处于这个状态的进程因为等待某种事件的发生而被挂起。;

T:暂停状态或跟踪状态;

X:退出状态,进程即将被销毁;

Z:退出状态,进程成为僵尸进程。

2.1 获取环境变量

获取环境变量的方式:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16 2.3 创建进程

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 接下来我们运行程序:

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.4 使用进程创建程序

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 运行结果如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.5 使用子进程加载新程序

在创建进程后子进程与父进程有相同的代码空间;实际应用中,需要子进程 去执行另外一个程序,可以在子进程中调用exec族函数它的代码段完全替换为 新的程序,并从这个新进程的main函数开始执行。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.6 wait()函数

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

  2.7 使用daemon创建守护进程

守护进程(Daemon)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件,它不需要用户输入就能运行并提供某种服务。

守护进程的父进程是init进程,因为它真正的父进程在fork出该子进程后就先于核子进 程exit退出了,所以它是-个由init领养的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出(无论是向标准输出设备还是标准错误输出设备的输出)都需要特殊处理。

运行后:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

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

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 运行如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_162.9管道

管道,即进程间数据流的通道。通常A进程输出连B进程输入端。符号“|"

1.匿名管道: pipe文件

函数原型:int pipe(int pipefd[2])

2.命名管道: fifo文件:int mkfifo(const char *pathname, mode_t mode)(ps:参数pathname指定了文件名

参数mode则指定了文件的读写权限)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.10 通过命名管道发送文件

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

  2.11 共享内存写数据

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.12 共享内存读数据

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 2.13 使用有名信号量同步共享内存实例

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16 

三.开发板

3.1 下载、安装、运行QEMU

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

必须在Ubunut的桌面环境下启动终端,执行./qemu-imx6ull-gui.sh

我们可以看到下面界面

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 3.2 打开LCD图像和屏幕

$ fb-test

$ cd myfb-test

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 $ ./myfb-test /dev/fb0

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

 3.3 串口EEPROM

$ cd

$ i2cdetect -l #列出所有ic2总线

$ i2cdetect -y 0 #列出总线0上的设备

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

3.4 命令控制LED

$ cd

$ cd led_driver_qemu/

$ insmod 100ask_led.ko

 

$ ./ledtest /dev/100ask_led0 on

$ ./ledtest /dev/100ask_led1 off

3.5 按键控制LED

安装驱动:

$ cd

$ cd button_driver_qemu/

$ insmod button_drv.ko #扫描你的按键

$ insmod board_100ask_qemu_imx6ull.ko 

启动按键控制

$ ./button_led_test

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATS3lhYjnlJ80OA==,size_20,color_FFFFFF,t_70,g_se,x_16

四、线程概念
所谓线程,就是操作系统所能调度的最小单位。普通的进程,只有一个线程在执行对应的逻辑。我们可以通过多线程编程,使一个进程可以去执行多个不同的任务。相比多进程编程而言,线程享有共享资源,即在进程中出现的全局变量,每个线程都可以去访问它,与进程共享内存空间,使得系统资源消耗减少。

举报

相关推荐

线程 进程 开发板

线程,进程,开发板

多线程-进程-开发板

线程、进程与开发板

线程、进程和使用开发板

多进程开发

Linux的多线程进程开发板

一起学习多线程、进程、开发板

0 条评论