【嵌入式】嵌入式Linux开发实战指南:从交叉编译到触摸屏交互

文章目录

  • 前言:
  • 1.简介
    • 1.1. 交叉编译工具
    • 1.2. 项目开发流程:
    • 1.3. ARM开发板的连接方法
  • 2. 开发板连接
  • 3. 系统文件 IO
  • 4. 设置共享文件夹
    • 3.1. 读文件
    • 3.2. 写文件
    • 3.2. 设置文件偏移量
  • 4. LCD显示屏显示
    • 4.1. LCD 显示颜色
    • 4.2. 将文件下载到开发板
      • 4.2.1. 在CRT链接开发板中输入命令"rx 需要下载的文件名"
    • 4.3. lcd 使用 write 函数直接写入像素点出现噪点等待一点后又能完全显示
    • 4.4. 开发板lcd 显示 bmp 图片
  • 5. 触摸屏
    • 5.1. 触摸屏 之 Linux 输入子系统模型
    • 5.1.1 input.h
    • 5.1.2 事件数据分析
  • 总结:

前言:

在嵌入式系统开发领域,交叉编译、系统文件IO操作、LCD显示以及触摸屏处理是一些基本且关键的技能。本文将详细介绍这些技能的实现方法和相关技术细节,旨在帮助开发者更好地理解和掌握嵌入式Linux开发过程中的常用操作。我们将从交叉编译工具的介绍开始,逐步深入到项目开发流程、开发板连接方法、系统文件IO的基本操作,再到LCD显示屏的显示技术以及触摸屏的Linux输入子系统模型和事件分析。通过本文的学习,读者将能够获得从硬件连接到软件编程的全面知识。

1.简介

1.1. 交叉编译工具

每个不同的平台可执行的格式都不尽相同,我们需要Linux系统的ARM平台执行程序,故需要ARM-Linux交叉编译工具,ubuntu 交叉编译工具链“arm-linux-gcc”

1.2. 项目开发流程:

1、使用C语言编写项目源代码
2、使用交叉编译工具编译项目源码
3、将编译生成的可执行程序下载到ARM开发板
4、在ARM开发板执行项目程序
5、验证项目程序的准确性

1.3. ARM开发板的连接方法

SecureCRT是一款支持SSH(SSH1和SSH2)的终端仿真程序,简单的说是Windows下登录UNIX或Linux服务器主机的软件。

2. 开发板连接

  1. 使用 串口线 与 usb 转串口线将开发板与电脑进行连接

  2. 检查电脑是否识别 usb 转串口驱动
    在这里插入图片描述

  3. 打开 CRT 软件

  4. 在快速链接向导里向导中进行配置
    在这里插入图片描述

  5. 打开开发板
    在这里插入图片描述

3. 系统文件 IO

  1. 打开文件 open
   #include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>int open(const char *pathname, int flags); // pathname:	需要打开的文件的路径名+文件名// flag:		打开文件的模式( O_RDONLY, O_WRONLY, or O_RDWR)// 返回值:	成功返回新的文件描述符,失败返回-1和出错码(perror)
  1. 关闭文件 close
   #include <unistd.h>int close(int fd);// fd:	文件描述符// 返回值: 成功返回0,失败返回-1和错误码
  1. 读取文件内容 read
   #include <unistd.h>ssize_t read(int fd, void *buf, size_t count);// fd:	文件描述符// buf:	读到的数据缓冲区// count:需要读取的字节数// 返回值: 成功返回实际度到的字节数,失败返回-1 和 错误码
  1. 写数据到文件中 write
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);// fd:	文件描述符// buf:	写到的数据缓冲区// count:需要写入的字节数// 返回值: 成功返回实际度写入字节数,失败返回-1 和 错误码
  1. 设置文件偏移量 Iseek
   #include <sys/types.h>#include <unistd.h>off_t lseek(int fd, off_t offset, int whence);  // fd:	文件描述符// offset:偏移量// whence:基准点(SEEK_SET开头、SEEK_CUR当前、SEEK_END结尾)// 返回值:成功返回文件新的文件偏移量,失败返回-1

4. 设置共享文件夹

  1. 打开VMware虚拟机打开设置
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在ubantu虚拟机中检查是否创建成功。

3.1. 读文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{// 1.打开文件int rd_fd = open("1.txt", O_RDONLY); if (rd_fd == -1) // 判断是否打开成功{perror("open 1.txt failed");exit(-1); // 退出程序}// 2.读取文件char buf[1024]; //定义缓冲区bzero(buf, sizeof(buf)); //清空缓冲区int ret = read(rd_fd, buf, sizeof(buf));if (ret == -1){perror("read 1.txt failed");exit(-2); // 退出程序}// 3.查看数据printf("read 1.txt %d byte is: %s\n", ret, buf);// 4.关闭文件close(rd_fd);
}

在这里插入图片描述

3.2. 写文件

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{// 1.打开文件int wd_fd = open("2.txt", O_WRONLY | O_CREAT, 0644); if (wd_fd == -1) // 判断是否打开成功{perror("open 1.txt failaed");exit(-1); // 退出程序}// 2.写数据int ret = write(wd_fd, "zhangsan hello", sizeof("zhangsan hello"));if (ret == -1){perror("write 2.txt failed");exit(-2); // 退出程序}// 4.关闭文件close(wd_fd);
}

在这里插入图片描述

3.2. 设置文件偏移量

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{// 1.打开文件int wd_fd = open("2.txt", O_WRONLY | O_CREAT, 0644); if (wd_fd == -1) // 判断是否打开成功{perror("open 1.txt failaed");exit(-1); // 退出程序}// 2.写数据int l_ret = lseek(wd_fd, 0, SEEK_END); // 将偏移量移动到文件末尾int ret = write(wd_fd, "zhangsan hello", sizeof("zhangsan hello"));if (ret == -1){perror("write 2.txt failed");exit(-2); // 退出程序}printf("lseek %d byte; write %d byte\n", l_ret, ret);// 4.关闭文件close(wd_fd);
}

在这里插入图片描述

4. LCD显示屏显示

4.1. LCD 显示颜色

lcd屏可显示显示像素点得组成ARGB四个元素组成,一个元素得有256个不同的值故需要8位二进制来描述,因此4个元素要需要32位(4字节)二进制来表示。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>int main()
{// 打开lcd设备int lcd_fd = open("/dev/fb0", O_RDWR);if (lcd_fd == -1){perror("open LCD failed");exit(-1);}// 定义色彩int color = 0xFF0000; // 假设是红色// 将色彩写入lcd设备文件for (int i = 0; i < 800 * 480; i++){write(lcd_fd, &color, sizeof(color)); //写一个像素点}  // 关闭lcd设备close(lcd_fd);return 0;
}

在这里插入图片描述

4.2. 将文件下载到开发板

4.2.1. 在CRT链接开发板中输入命令"rx 需要下载的文件名"

在这里插入图片描述
通过Xmode发送
在这里插入图片描述
发送完成
在这里插入图片描述
下载文件执行成功后修改文件权限,修改文件权限后方可执行
在这里插入图片描述
屏幕显示红色:
请添加图片描述

4.3. lcd 使用 write 函数直接写入像素点出现噪点等待一点后又能完全显示

问题分析:由于系统调用需要花费时间
解决办法:给 lcd 申请一片显存
使用 mmap 函数可以采用内存映射的方式来为 lcd 映射一块特殊的内存作为 lcd 的显存

#include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); // 映射函数 
// 主要参数:
// addr:	映射内存的起始地址(NULL表述由内核自己找到符合要求的地址)
// length:	映射内存的大小
// prot: 	映射内存的权限(与 open 的权限一致)
//       		PROT_EXEC  Pages may be executed.
//       		PROT_READ  Pages may be read.
//       		PROT_WRITE Pages may be written.
//      		PROT_NONE  Pages may not be accessed.
// flags: 	映射内存的更新方式
//				MAP_SHARED: 共享内存的方式更新(更新已有的内存)
//				MAP_PRIVATE: 创建新的内存并更新
// fd: 		需要映射的文件描述符
// offset: 	映射内存的偏移量
// 返回值:
//	成功返回映射内存基地址
//	失败返回 MAP_FAILED 和 错误码int munmap(void *addr, size_t length); // 解除映射函数

显示绿色:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>int main()
{int i;// 打开lcd设备int lcd_fd = open("/dev/fb0", O_RDWR);if (lcd_fd == -1){perror("open LCD failed");exit(-1);}// 开启映射int* lcd_map = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);// 定义色彩int color = 0x00FF00; // 假设是绿色// 将色彩写入lcd设备文件for (i = 0; i < 800 * 480; i++){*(lcd_map + i) = color; // 显示一个像素点}  // 关闭lcd设备close(lcd_fd);// 关闭映射munmap(lcd_map, 800 * 480);return 0;
}

请添加图片描述

4.4. 开发板lcd 显示 bmp 图片

  1. 常见的图片格式:jpeg / jpg, png, bmp
  2. jpeg / jpg: 采用专用的图像压缩算法进行压缩
    bmp: 它采用位映射存储格式,除了图像深度可选外,不采用其他任何压缩,因此,BMP 文件所占用的空间很大(推荐24位的位图)。
    在这里插入图片描述
    分析:由于 lcd 显示的像素点是 32位 的彩色,而bmp图片的像素点是 24位,所以需要要完成 24位 到 32位 的转换
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>int main()
{int i;// 打开lcd设备int lcd_fd = open("/dev/fb0", O_RDWR);if (lcd_fd == -1){perror("open LCD failed");exit(-1);}// 开启映射int* lcd_map = mmap(NULL, 800*480*4, PROT_READ|PROT_WRITE, MAP_SHARED, lcd_fd, 0);if (lcd_map == MAP_FAILED){perror("mmap failed");close(lcd_fd);exit(-1);}// 打开bmp图片int bmp_fd = open("bgt.bmp", O_RDONLY);if (bmp_fd == -1){perror("open BMP failed");munmap(lcd_map, 800*480*4);close(lcd_fd);exit(-1);}// 跳过BMP文件头(假设54字节标准头)lseek(bmp_fd, 54, SEEK_SET);// 读取图片数据int bmp_buf[800*480]; // 图片的大致大小char tmp_buf[800*480*3]; bzero(bmp_buf, sizeof(bmp_buf)); // 清除缓冲区bzero(tmp_buf, sizeof(tmp_buf));read(bmp_fd, tmp_buf, sizeof(tmp_buf)); // 读取数据// 关闭bmp图片文件close(bmp_fd);// 将 24位 的像素点转换为 32位for (i = 0; i < 800*480; ++i){bmp_buf[i] = tmp_buf[i*3]|tmp_buf[i*3+1]<<8|tmp_buf[i*3+2]<<16|0x00<<24;}// 显示for (i = 0; i < 800*480; i++){*(lcd_map + i) = bmp_buf[i]; // 显示一个像素点} // 关闭lcd设备close(lcd_fd);// 关闭映射munmap(lcd_map, 800*480*4);return 0;
}

请添加图片描述
但是图片是反转过来的
在这里插入图片描述

// 将 24位 的像素点转换为 32位,并将图片翻转过来
for (i = 0; i < 480; ++i) {for (j = 0; j < 800; ++j) {bmp_buf[i*800+j] = tmp_buf[((479-i)*800 + j)*3] | tmp_buf[((479-i)*800 + j)*3+1]<<8 | tmp_buf[((479-i)*800 + j)*3+2]<<16 | 0x00<<24;}
}

现在就正了:
请添加图片描述

5. 触摸屏

5.1. 触摸屏 之 Linux 输入子系统模型

可以通过查看 input.h 的代码,了解输入子系统的框架

cd /usr/include/linux/

5.1.1 input.h

/** The event structure itself*/struct input_event {struct timeval time; // 事件发生的时间__u16 type;			 // 事件发生类型__u16 code;			 // 事件的代码__s32 value;		 // 事件的值
};

在开发板上有这样一些事件:
在这里插入图片描述

/** Event types*/#define EV_SYN			0x00
#define EV_KEY			0x01
#define EV_REL			0x02
#define EV_ABS			0x03
#define EV_MSC			0x04
#define EV_SW			0x05
#define EV_LED			0x11
#define EV_SND			0x12
#define EV_REP			0x14
#define EV_FF			0x15
#define EV_PWR			0x16
#define EV_FF_STATUS		0x17
#define EV_MAX			0x1f
#define EV_CNT			(EV_MAX+1)
/** Absolute axes*/#define ABS_X			0x00
#define ABS_Y			0x01
#define ABS_Z			0x02
#define ABS_RX			0x03
#define ABS_RY			0x04
#define ABS_RZ			0x05
#define ABS_THROTTLE		0x06
#define ABS_RUDDER		0x07
#define ABS_WHEEL		0x08
#define ABS_GAS			0x09
#define ABS_BRAKE		0x0a
// ...

5.1.2 事件数据分析

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#include<linux/input.h>int main(void)
{// 打开触摸屏int ts_fd = open("/dev/input/event0", O_RDONLY);if(ts_fd == -1){perror("open touchscreen failed");exit(-1);}// 定义输入事件缓冲区struct input_event myevent;while(1){// 读入数据并输出read(ts_fd, &myevent, sizeof(struct input_event)); //阻塞等待输入数据printf("type:%d code:%d value:%d\n", myevent.type, myevent.code, myevent.value);}// 关闭文件close(ts_fd);return 0;
}

在这里插入图片描述

type:0 code:0 value:0 // 同步事件
type:3/*EV_ABS触摸屏事件*/ code:0/*ABS_X x轴*/ value:520
type:3/*EV_ABS触摸屏事件*/ code:1/*ABS_Y y轴*/ value:457
type:0 code:0 value:0 // 同步事件
type:1/*EV_KEY键盘事件*/ code:330/*BTN_TOUCH键盘事件*/ value:0//松开
type:0 code:0 value:0 // 同步事件

获取触摸屏 的 x,y值:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>#include<linux/input.h>int main(void)
{// 打开触摸屏int ts_fd = open("/dev/input/event0", O_RDONLY);if(ts_fd == -1){perror("open touchscreen failed");exit(-1);}// 定义输入事件缓冲区struct input_event myevent;int x, y, count = 0;while(1){// 读入数据并输出read(ts_fd, &myevent, sizeof(struct input_event)); //阻塞等待输入数据if(myevent.type == EV_ABS) // 触摸屏事件{if(myevent.code == ABS_X) // X轴{x = myevent.value;count++;}if(myevent.code == ABS_Y){y=myevent.value;count++;}if (count == 2) {count = 0;printf("(%d, %d)\n", x, y);}}//printf("type:%d code:%d value:%d\n", myevent.type, myevent.code, myevent.value);}// 关闭文件close(ts_fd);return 0;
}

在这里插入图片描述

总结:

本文全面介绍了嵌入式Linux开发中的一系列关键技术,包括交叉编译工具的使用、项目开发流程、开发板的连接方法、系统文件IO的基本操作、LCD显示屏的显示技术以及触摸屏的输入子系统模型和事件分析。通过详细的代码示例和步骤说明,读者可以对这些技术有一个清晰的认识,并能够在实际开发中灵活应用。

交叉编译工具是开发过程中不可或缺的一部分,它允许开发者在不同平台之间进行代码的编译和移植。而项目开发流程的介绍,为读者提供了一个清晰的开发路线图,确保开发工作的有序进行。开发板的连接方法和系统文件IO操作是进行硬件交互的基础,LCD显示屏的显示技术和触摸屏事件分析则进一步扩展了开发者在用户界面交互方面的技能。

通过本文的学习,开发者不仅能够掌握嵌入式Linux开发的基本技能,还能够对LCD显示和触摸屏处理等高级主题有更深入的理解。希望本文能够成为嵌入式Linux开发者的一份宝贵参考资料,帮助他们在项目开发中更加得心应手。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/30067.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

002.Linux CentOS7 安装

我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448; 入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448; 虚 拟 环 境 搭 建 &#xff1a;&#x1f449;&…

Git Extensions gui工具差异显示乱码

某些IDE例如KEIL等默认编码格式为GB2312&#xff0c;而git extensions默认utf-8&#xff0c;如果不想修改文件格式为utf-8的话就修改git extensions格式为GB2312。 默认是没有chines 这个选项的&#xff0c;我这里是已经添加好的。方法为上方工具栏->设置->Git->设置…

Linux C编译器从零开发三

AST语法树 BNF抽象 expr equality equality relational ("" relational | "!" relational)* relational add ("<" add | "<" add | ">" add | ">" add)* add mul ("" …

为什么很多Java程序员会下意识觉得Java的就是最好的?

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「Java的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01;做为一个真正热爱编程&#…

【并发程序设计】总篇集 Linux下 C语言 实现并发程序

11_Concurrent_Programing 文章目录 11_Concurrent_Programing1.进程概念进程内容进程类型进程状态 2.进程常用命令进程信息命令top 命令进程信息表 进程优先级命令nice 命令renice 命令 后台进程命令 3.子进程创建子进程fork 函数 结束进程exit 函数_exit 函数 回收子进程wait…

功能测试 之 单模块测试----抢购模块

1.先测后台&#xff0c;再测前台 面试题1: 当你发现研发实现的结果与需求不一致时怎么办? 需求评审的时候&#xff1a;需要确认所有输入类型的校验是针对单独的输入框做的还是在最终提交时校验 抢购模块&#xff1a;需求跟实现的内容不一致 (跟产品和研发一起确认。研发为什…

【Python教程】如何搭建一个高效的Python开发环境?结尾附安装包直通车

前言&#xff1a; Python 丰富的函数库和组件库是这门语言强大的核心原因&#xff01;但我们不可能去记忆所有的方法名和参数名&#xff0c;往往只能记住一些常用的或者某个方法开头的几个字母。这个时候一个好的开发工具就需要能聪明地“猜”出你想输入的代码&#xff0c;并给…

Java数据结构与算法——稀疏数组和队列

一、稀疏数组sparsearray数组 该二维数组的很多值是默认值0,因此记录了很多没有意义的数据&#xff0c;可以采用稀疏数组进行压缩 1.基本介绍: 当一个数组中大部分元素为0&#xff0c;或者为同一个值的数组时&#xff0c;可以使用稀疏数组来保存该数组。 稀疏数组的处理方法…

深入解析Linux权限管理:从基本原理到应用

目录 Shell 命令及运行原理 Shell 与 Kernel Linux 权限的概念 命令提示符 Linux 权限管理 1. 访问者的分类 ugo 2. 类型和访问权限 3. 权限值表示方法 4. chmod 访问权限设置 掩码命令&#xff1a;umask 5.目录权限 粘滞位&#xff1a; 文章手稿见文末 Shell 命令…

Unity OpenCVForUnity 安装和第二个案例详解 <二>

目录 一、前言 二、场景介绍 1.WebCamTextureToMatExample脚本 2.FpsMonitor脚本 三、 结构体Scaler 四、找到相机并使用 1.相机的启用 2.格式转换 a.把webCamTexture转换成Mat b.把Mat转换成Texture2D 五、脚本组合 六、作者的碎碎念 一、前言 第二个案例&#xf…

大语言模型的昨天、今天和明天

引言 近年来&#xff0c;人工智能&#xff08;AI&#xff09;技术突飞猛进&#xff0c;其中大语言模型&#xff08;LLM&#xff09;无疑是最引人瞩目的技术之一。从OpenAI的GPT系列到Meta的Llama模型&#xff0c;大语言模型的发展不仅改变了人们对AI的认知&#xff0c;也在各行…

通过防抖动代码解决ResizeObserver loop completed with undelivered notifications.

通过防抖动代码解决ResizeObserver loop completed with undelivered notifications. 一、报错内容二、解决方案解释&#xff1a; 一、报错内容 我通过el-tabs下的el-tab-pane切换到el-table出现的报错&#xff0c;大致是渲染宽度出现了问题 二、解决方案 扩展原生的 Resiz…

DevOps学习回顾01-技能发展路线-岗位能力-体系认知

事为先&#xff0c;人为重–事在人为 参考来源&#xff1a; 极客时间专栏&#xff1a;DevOps实战笔记&#xff0c;作者&#xff1a;石雪峰 课程链接&#xff1a;https://time.geekbang.org/column/intro/235 时代的典型特征 VUCA VUCA 是指易变性&#xff08;Volatility&…

破局者:Codebeamer如何打破传统束缚,开启工程新纪元

飞速发展的数字时代&#xff0c;一场深刻的数字化革命正在重塑各行各业的价值链条&#xff0c;为产品开发组织带来了前所未有的挑战。随着电子技术和软件组件在产品设计中的地位日益凸显&#xff0c;传统的工程实践正经历着一场深刻的变革。为了顺应这一潮流&#xff0c;企业必…

【碳排放控排1006】碳排放控排企业名单数据集,探索绿色生产!

今天给大家分享的是国内顶级期刊2023发表论文《碳排放规制、企业减排激励与全要素生产率——基于中国碳排放权交易机制的准自然实验》中使用到的重要数据集——碳排放控排企业名单&#xff0c;该论文从企业生产效率视角对论文进行研究&#xff0c;发现碳排放权交易机制显著提升…

植物大战僵尸杂交版V2.1快速刷金币的方法(新号适用,无需自带招财猫)

&#x1f4dd;个人主页&#xff1a;哈__ 期待您的关注 目录 1. &#x1f4bb;游戏介绍 2. &#x1f525;快速刷取金币的办法&#xff08;我是新号测试的&#xff09; 2.1 无招财猫 2.2 有招财猫 《植物大战僵尸杂交版》是一款在原版《植物大战僵尸》基础上进行了创新的塔防…

Java学习【深入解读File类:从基础到高级的完整指南】

Java学习【深入解读File类&#xff1a;从基础到高级的完整指南】 ⭐File的概述和构造方法⭐File常见的成员方法&#x1f319;构造方法&#x1f319;length()&#x1f319;getAbsoluteFile()和getPath()&#x1f319;getName()和lastModified() ⭐文件的创建和删除⭐获取并遍历 …

【OpenHarmony开发】 tracepoint的机制总结

一、tracepoint 的机制 1.1 DECLARE_HOOK 解析 DECLARE_HOOK(vendor_bond_check_dev_link,TP_PROTO(const struct bonding *bond, const struct slave *slave, int *state), TP_ARGS(bond, slave, state)); ​ // 在已经实现如下宏定义的前提下 // CONFIG_TRACEPOINTS 和 CO…

AbMole带你探索颅内压力与肌肉生长的联系:一项突破性研究

在生物医学领域&#xff0c;颅内压力&#xff08;ICP&#xff09;的调控机制一直是研究的热点。最近&#xff0c;一项发表在《PLOS ONE》上的研究为我们揭示了颅内压力与后颅窝肌肉生长之间的潜在联系&#xff0c;为我们理解某些慢性头痛的成因提供了新的视角。 颅内压力的异常…

temu跨境选品师是怎么样的一个项目?

TEMU(特穆)跨境选品师项目&#xff0c;作为一项创新的全球商品采购和选品服务&#xff0c;正在逐步改变消费者对于跨境电商产品的认知和选择方式。这个项目不仅仅是一个简单的商品推荐平台&#xff0c;更是一种以数据驱动的精准选品策略的体现&#xff0c;为消费者提供了全新的…