📚 本文是《嵌入式 Linux 应用开发学习笔记》系列第 06 / 7 篇:输入系统、网络编程与多线程。返回系列目录。
第7章 输入系统应用编程(未完成)
7.1输入设备
键盘、鼠标、遥控杆、书写板、触摸屏等与linux完成数据交换
输入设备种类繁多,能否统一它们的接口?
Linux 为了统一管理输入设备,实现了一套能兼容所有输入设备的框架:输入系统
7.2输入系统框架及调试
输入系统框架

示例:
在开发板上执行,可以看到触摸屏数据
hexdump /dev/input/event1
hexdump: 是一个命令行工具,它将文件或数据流的内容以十六进制和 ASCII 格式输出
/dev/input/event1: 是一个特殊的设备文件,代表一个输入设备,比如键盘、鼠标或触摸板。Linux 内核会把来自这些设备的原始输入事件(例如按键、鼠标移动或点击)写入这些文件
7.2.2编写APP需要掌握的知识
驱动程序上报的数据含义三项重要内容:
1.type:哪类,如EV_KEY为按键类
2.code:哪个,比如KEY_A
3.value:值,比如0按下,1松开
- 此外APP 读取数据时,可以得到一个或多个数据,比如一个触摸屏的一个触点会上报 X、Y 位置信息,也可能会上报压力值
- 驱动程序上报完一系列的数据后,会上报一个“同步事件”,表示数据上报完毕。APP 读到“同步事件”时,就知道已经读完了当前的数据
- 同步事件也是一个 input_event 结构体,它的 type、code、value 三项都是 0

7.2.3调试技巧
确定设备信息
ls /dev/input/* -l
可以看到设备

确定设备对应的硬件
cat /proc/bus/input/devices
7.3不用库的应用编程
APP访问硬件有4种方式:查询方式、休眠-唤醒、poll方式、异步通知
通过 ioctl 获取设备信息:
int ioctl(int fd, unsigned long request, ...);
比如要读取输入设备的 evbit 时,ioctl 的 request 要写为“EVIOCGBIT(0, size)
![]()
7.3.1查询、休眠唤醒方式
if (argc < 2)
{
printf("Usage: %s <dev> [noblock]\n", argv[0]);
return -1;
}
if (argc == 3 && !strcmp(argv[2], "noblock"))
{
fd = open(argv[1], O_RDWR | O_NONBLOCK);
}
else
{
fd = open(argv[1], O_RDWR);
}
while (1)
{
len = read(fd, &event, sizeof(event));
if (len == sizeof(event))
{
printf("get event: type = 0x%x, code = 0x%x, value = 0x%x\n", event.type, event.code, event.value);
}
else
{
printf("read err %d\n", len);
}
}
7.3.2poll/select方式
POLL 机制、SELECT 机制是完全一样的,只是 APP 接口函数不一样
第8章 网络通信
8.1网络通信概述
实际还是数据传输
数据传输三要素:源、目的、长度。
现在假设A、B两台计算机通讯,一台为服务器,一台为客户端。
访问网站的话,设计网站服务器、浏览器,网站服务器平时安静地呆着,浏览器主动发起数据请求
服务器:被动地响应请求
客户端:主动地发起请求

数据传输两种方式:TCP、UDP。
TCP:可靠的、有重传机制(确保数据真到达)、适合控制命令
UDP:不可靠的(适合视频、语音等),视频通话时,使用 UDP,偶尔的丢包、偶尔的花屏时可以忍受的
怎么写程序?
仿照文件读写
将fd=open(”文件名“);
read(fd,buf,len);//源、目的、长度
8.1.1IP和端口
数据传输:源、目的、长度

源端口区分不同浏览器,目的端口区分想要服务
8.1.3两种传输方式TCP/UDP
网络协议5层:物理层、数据链路层、网络层、传输层、应用层
应用层:直接为用户进程提供服务,如支持www的HTTP协议、电子邮箱SMTP协议、文件传输FTP协议,DNS、POP3、FNMP、Telnet
传输层:负责向两个主机中进程之间的通信提供服务,主要TCP、UDP
8.2TCP网络编程
服务端
- socket函数
int socket(int domain, int type,int protocol);
用于创建套接字,根本不涉及什么源、目的、长度,
- bind函数
fd = socket(.....);
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
从函数用于将地址绑定到一个套接字(自己的IP端口)
把fd和ip端口绑定,以后就检测这个ip端口看看数据有没有
- listen函数
int listen(int sockfd,int backlog);
启动检测数据
- accept函数
int accept(int sockfd, struct sockaddr *addr,int *addrlen);
建立一条连接,接收连接
- send函数
ssize_t send(int sockfd, const void *buf, size_t len, int flags);
发数据
- recv函数
ssize_t recv(int sockfd, void *buf, size_t len, int flags);
收数据
客户端
- socket函数
fd=socket(......)
- connect函数
int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);
建立连接
- recv
- send
8.3UDP网络编程
服务端
- socket函数
int socket(int domain, int type,int protocol);
用于创建套接字,根本不涉及什么源、目的、长度,
- bind函数
fd = socket(.....);
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
从函数用于将地址绑定到一个套接字(自己的IP端口)
- recvfrom
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
recvfrom 通常用于无连接套接字,因为此函数可以获得发送者的地址。
src_addr 是一个 struct sockaddr 类型的变量,该变量保存源机的 IP 地
址及端口号。
addrlen 常置为 sizeof (struct sockaddr)。
- sendto
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen);
客户端
- socket函数
fd=socket(......)
- connect函数
int connect(int sockfd, struct sockaddr * serv_addr,int addrlen);
建立连接
- recvfrom,recv
- sendto,send
第9章 多线程编程
9.1线程的使用
9.1.1为什么使用多线程
编写代码时有时候要做2件事,如一边屏幕播放视频,一边等待用户按键操作
如果使用多线程,线程1单独处理按键,线程2单独处理播放
9.1.2线程概念
操作系统所能调度的最小单位,普通的进程,只有一个线程执行逻辑。
我们可以通过多线程编程,使一个进程可以去执行多个不同的任务
相比多进程编程,线程享有共享资源,在进程中出现的全局变量,每个线程都可以访问
9.1.3线程的标识pthread_t
对进程:每个进程有唯一PID
对线程:有tid,本质是pthread_t类型的变量
测试例程
#include <pthread.h>
#include <stdio.h>
int main()
{
pthread_t tid = pthread_self();//获取主线程的 tid 号
printf("tid = %lu\n",(unsigned long)tid);
return 0;
}
gcc xxx.c -lpthread 方可编译多线程程序
9.1.4线程的创建
- pthread_create
int pthread_create( pthread_t *thread,
const pthread_attr_t *attr,
void *(*start_routine) (void *),
void *arg);
例程
| |
9.1.5同步操作-向线程传数据(等待)
| |
9.1.6同步操作(信号量)
// 初始化
#include <semaphore.h>
static sem_t sem;
int sem_init(sem_t *sem,int pshared,unsigned int value);
等待/释放:
#include <pthread.h>
int sem_wait(sem_t *sem);
int sem_post(sem_t *sem);
| |
9.1.7同步操作(互斥量)
static pthread_mutex_t g_tMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&g_tMutex);
pthread_mutex_unlock(&g_tMutex);
给不希望打断的内容加锁
| |