Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长
在人类的发展进化中,时间是一个非常重要神秘的物质量。任何事物都是在时间的长河中流淌发生、发展、变化。我们进行驱动开发中对时间的定义和使用也是必须要掌握的重要知识点。
本节笔记主要学习Linux内核定时器的驱动开发,主要包括内核时间管理和定时器、硬件原理图分析【LED】、驱动开发和测试。最重要的内容为定时器驱动开发部分。
本笔记的脑图如下:
一、Linux时间管理和内核定时器
1.内核时间管理
作为一个应用者,不需要研究太深的具体实现。会用相应的API函数即可。
图形化配置界面可以设置系统节拍率。具体路径为:
Kernel Features
Timer frequency(<choice>[=y])
使用CONFIG_HZ来设置自己的系统时钟。
HZ表示一秒的节拍数,也就是频率。
使用jiffies来记录系统从启动以来的系统节拍数。
jiffies/HZ就是系统运行时间,单位为秒。
处理32位jiffies的绕回,用到的几个函数。如下:
函数 | 描述 |
time_after(unknown,known) | unkonwn超过known时为真 |
time_before(unknown,known) | unkonwn没有超过known时为真 |
time_after_eq(unknown,known) | unkonwn超过或等于known时为真 |
time_before_eq(unknown,known) | unkonwn没有超过或等于known时为真 |
2.内核定时器
需要周期性处理的工作都要用到定时器。Linux定时器采用系统时钟来实现,只需要提供超时时间和定时处理函数即可。
内核定时器超时会自动关闭。
使用timer_list结构体表示内核定时器。该结构体的定义如下:
struct timer_list {
struct list_head entry;
unsigned long expires; /* 定时器超时时间,单位是节拍数 */
struct tvec_base *base;
void (*function)(unsigned long); /* 定时处理函数 */
unsigned long data; /* 要传递给 function 函数的参数 */
int slack;
};
定义好定时器以后,需要以下函数对其进行初始化:
函数 | 说明 |
init_timer | 初始化 |
add_timer | 注册 |
del_timer | 删除 |
del_timer_sync | 等待其他处理器使用完定时器后删除 |
mod_timer | 修改定时值 |
内核定时器的使用流程如下:
1 struct timer_list timer; /* 定义定时器 */
2
3 /* 定时器回调函数 */
4 void function(unsigned long arg)
{
6 /*
7 * 定时器处理代码
8 */
9
10 /* 如果需要定时器周期性运行的话就使用 mod_timer
11 * 函数重新设置超时值并且启动定时器。
12 */
13 mod_timer(&dev->timertest, jiffies + msecs_to_jiffies(2000));
14 }
15
16 /* 初始化函数 */
17 void init(void)
18 {
19 init_timer(&timer); /* 初始化定时器 */
20
21 timer.function = function; /* 设置定时处理函数 */
22 timer.expires=jffies + msecs_to_jiffies(2000);/* 超时时间 2 秒 */
23 timer.data = (unsigned long)&dev; /* 将设备结构体作为参数 */
24
25 add_timer(&timer); /* 启动定时器 */
26 }
27
28 /* 退出函数 */
29 void exit(void)
30 {
31 del_timer(&timer); /* 删除定时器 */
32 /* 或者使用 */
33 del_timer_sync(&timer);
34 }
3.Linux内核短延时函数
函数 描述
void ndelay(unsigned long nsecs) 纳秒
void udelay(unsigned long usecs) 微秒
void mdelay(unsigned long mseces) 毫秒
二、硬件原理图分析
LED0 接到了 GPIO_3 上, GPIO_3 就是 GPIO1_IO03,当 GPIO1_IO03输出低电平(0)的时候发光二极管 LED0 就会导通点亮,当 GPIO1_IO03 输出高电平(1)的时候发光二极管 LED0 不会导通,因此 LED0 也就不会点亮。所以 LED0 的亮灭取决于 GPIO1_IO03的输出电平,输出 0 就亮,输出 1 就灭。
三、驱动程序开发
1.修改设备树文件
使用已有的即可。
2.定时器驱动程序开发
38 struct timer_dev{
39 dev_t devid; /* 设备号 */
40 struct cdev cdev; /* cdev */
41 struct class *class; /* 类 */
42 struct device *device; /* 设备 */
43 int major; /* 主设备号 */
44 int minor; /* 次设备号 */
45 struct device_node *nd; /* 设备节点 */
46 int led_gpio; /* key 所使用的 GPIO 编号 */
47 int timeperiod; /* 定时周期,单位为 ms */
48 struct timer_list timer; /* 定义一个定时器 */
49 spinlock_t lock; /* 定义自旋锁 */
50 };
定时器设备结构体,在 48 行定义了一个定时器成员变量 timer。
60 static int led_init(void)
61 {
62 int ret = 0;
63
64 timerdev.nd = of_find_node_by_path("/gpioled");
65 if (timerdev.nd== NULL) {
66 return -EINVAL;
67 }
68
69 timerdev.led_gpio = of_get_named_gpio(timerdev.nd ,"led-gpio",
0);
70 if (timerdev.led_gpio < 0) {
71 printk("can't get led\r\n");
72 return -EINVAL;
73 }
74
75 /* 初始化 led 所使用的 IO */
76 gpio_request(timerdev.led_gpio, "led"); /* 请求 IO */
77 ret = gpio_direction_output(timerdev.led_gpio, 1);
78 if(ret < 0) {
79 printk("can't set gpio!\r\n");
80 }
81 return 0;
82 }
LED 灯初始化函数,从设备树中获取 LED 灯信息,然后初始化相应的 IO。
91 static int timer_open(struct inode *inode, struct file *filp)
92 {
93 int ret = 0;
94 filp->private_data = &timerdev; /* 设置私有数据 */
95
96 timerdev.timeperiod = 1000; /* 默认周期为 1s */
97 ret = led_init(); /* 初始化 LED IO */
98 if (ret < 0) {
99 return ret;
100 }
101 return 0;
102 }
函数 timer_open,对应应用程序的 open 函数,应用程序调用 open 函数打开/dev/timer 驱动文件的时候此函数就会执行。此函数设置文件私有数据为 timerdev,并且初始化定时周期默认为 1 秒,最后调用 led_init 函数初始化 LED 所使用的 IO。
111 static long timer_unlocked_ioctl(struct file *filp,
unsigned int cmd, unsigned long arg)
112 {
原子哥在线教学:www.yuanzige.com 论坛:www.openedv.com
1228
I.MX6U 嵌入式 Linux 驱动开发指南
113 struct timer_dev *dev = (struct timer_dev *)filp->private_data;
114 int timerperiod;
115 unsigned long flags;
116
117 switch (cmd) {
118 case CLOSE_CMD: /* 关闭定时器 */
119 del_timer_sync(&dev->timer);
120 break;
121 case OPEN_CMD: /* 打开定时器 */
122 spin_lock_irqsave(&dev->lock, flags);
123 timerperiod = dev->timeperiod;
124 spin_unlock_irqrestore(&dev->lock, flags);
125 mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(timerperiod));
126 break;
127 case SETPERIOD_CMD: /* 设置定时器周期 */
128 spin_lock_irqsave(&dev->lock, flags);
129 dev->timeperiod = arg;
130 spin_unlock_irqrestore(&dev->lock, flags);
131 mod_timer(&dev->timer, jiffies + msecs_to_jiffies(arg));
132 break;
133 default:
134 break;
135 }
136 return 0;
137 }
函数 timer_unlocked_ioctl,对应应用程序的 ioctl 函数,应用程序调用 ioctl函数向驱动发送控制信息,此函数响应并执行。此函数有三个参数: filp, cmd 和 arg,其中 filp是对应的设备文件, cmd 是应用程序发送过来的命令信息, arg 是应用程序发送过来的参数,在本章例程中 arg 参数表示定时周期。
CLOSE_CMD: 关闭定时器命令, 调用 del_timer_sync 函数关闭定时器。
OPEN_CMD:打开定时器命令,调用 mod_timer 函数打开定时器,定时周期为 timerdev 的
timeperiod 成员变量,定时周期默认是 1 秒。
SETPERIOD_CMD:设置定时器周期命令,参数 arg 就是新的定时周期,设置 timerdev 的
timeperiod 成员变量为 arg 所表示定时周期指。并且使用 mod_timer 重新打开定时器,使定时器
以新的周期运行。
139 /* 设备操作函数 */
140 static struct file_operations timer_fops = {
141 .owner = THIS_MODULE,
142 .open = timer_open,
143 .unlocked_ioctl = timer_unlocked_ioctl,
144 };
定时器驱动操作函数集 timer_fops。
146 /* 定时器回调函数 */
147 void timer_function(unsigned long arg)
148 {
149 struct timer_dev *dev = (struct timer_dev *)arg;
150 static int sta = 1;
151 int timerperiod;
152 unsigned long flags;
153
154 sta = !sta; /* 每次都取反,实现 LED 灯反转 */
155 gpio_set_value(dev->led_gpio, sta);
156
157 /* 重启定时器 */
158 spin_lock_irqsave(&dev->lock, flags);
159 timerperiod = dev->timeperiod;
160 spin_unlock_irqrestore(&dev->lock, flags);
161 mod_timer(&dev->timer, jiffies +
msecs_to_jiffies(dev->timeperiod));
162 }
函数 timer_function,定时器服务函数,此函有一个参数 arg,在本例程中arg 参数就是 timerdev 的地址,这样通过 arg 参数就可以访问到设备结构体。当定时周期到了以后此函数就会被调用。在此函数中将 LED 灯的状态取反,实现 LED 灯闪烁的效果。因为内核定时器不是循环的定时器,执行一次以后就结束了,因此在 161 行又调用了 mod_timer 函数重新开启定时器。
169 static int __init timer_init(void)
170 {
171 /* 初始化自旋锁 */
172 spin_lock_init(&timerdev.lock);
173
174 /* 注册字符设备驱动 */
175 /* 1、创建设备号 */
176 if (timerdev.major) { /* 定义了设备号 */
177 timerdev.devid = MKDEV(timerdev.major, 0);
178 register_chrdev_region(timerdev.devid, TIMER_CNT,
TIMER_NAME);
179 } else { /* 没有定义设备号 */
180 alloc_chrdev_region(&timerdev.devid, 0, TIMER_CNT,
TIMER_NAME);
181 timerdev.major = MAJOR(timerdev.devid); /* 获取主设备号 */
182 timerdev.minor = MINOR(timerdev.devid); /* 获取次设备号 */
183 }
184
185 /* 2、初始化 cdev */
186 timerdev.cdev.owner = THIS_MODULE;
187 cdev_init(&timerdev.cdev, &timer_fops);
188
189 /* 3、添加一个 cdev */
190 cdev_add(&timerdev.cdev, timerdev.devid, TIMER_CNT);
191
192 /* 4、创建类 */
193 timerdev.class = class_create(THIS_MODULE, TIMER_NAME);
194 if (IS_ERR(timerdev.class)) {
195 return PTR_ERR(timerdev.class);
196 }
197
198 /* 5、创建设备 */
199 timerdev.device = device_create(timerdev.class, NULL,
timerdev.devid, NULL, TIMER_NAME);
200 if (IS_ERR(timerdev.device)) {
201 return PTR_ERR(timerdev.device);
202 }
203
204 /* 6、初始化 timer,设置定时器处理函数,还未设置周期,所有不会激活定时器 */
205 init_timer(&timerdev.timer);
206 timerdev.timer.function = timer_function;
207 timerdev.timer.data = (unsigned long)&timerdev;
208 return 0;
209 }
第 169~209 行,函数 timer_init,驱动入口函数。在第 205~207 行初始化定时器,设置定时器的定时处理函数为 timer_function,另外设置要传递给 timer_function 函数的参数为 timerdev的地址。在此函数中并没有调用 timer_add 函数来开启定时器,因此定时器默认是关闭的,除非应用程序发送打开命令。
216 static void __exit timer_exit(void)
217 {
218
219 gpio_set_value(timerdev.led_gpio, 1); /* 卸载驱动的时候关闭 LED */
220 del_timer_sync(&timerdev.timer); /* 删除 timer */
221 #if 0
222 del_timer(&timerdev.tiemr);
223 #endif
224
225 /* 注销字符设备驱动 */
226 cdev_del(&timerdev.cdev); /* 删除 cdev */
227 unregister_chrdev_region(timerdev.devid, TIMER_CNT);
228
229 device_destroy(timerdev.class, timerdev.devid);
230 class_destroy(timerdev.class);
231 }
驱动出口函数,在 219 行关闭 LED,也就是卸载驱动以后 LED 处于熄灭状态。第 220 行调用 del_timer_sync 函数删除定时器,也可以使用 del_timer 函数。
3.编写测试APP
21 /* 命令值 */
22 #define CLOSE_CMD (_IO(0XEF, 0x1)) /* 关闭定时器 */
23 #define OPEN_CMD (_IO(0XEF, 0x2)) /* 打开定时器 */
24 #define SETPERIOD_CMD (_IO(0XEF, 0x3)) /* 设置定时器周期命令 */
25
26 /*
27 * @description : main 主程序
28 * @param - argc : argv 数组元素个数
29 * @param - argv : 具体参数
30 * @return : 0 成功;其他 失败
31 */
32 int main(int argc, char *argv[])
33 {
34 int fd, ret;
35 char *filename;
36 unsigned int cmd;
37 unsigned int arg;
38 unsigned char str[100];
39
40 if (argc != 2) {
41 printf("Error Usage!\r\n");
42 return -1;
43 }
44
45 filename = argv[1];
46
47 fd = open(filename, O_RDWR);
48 if (fd < 0) {
49 printf("Can't open file %s\r\n", filename);
50 return -1;
51 }
52
53 while (1) {
54 printf("Input CMD:");
55 ret = scanf("%d", &cmd);
56 if (ret != 1) { /* 参数输入错误 */
57 gets(str); /* 防止卡死 */
58 }
59
60 if(cmd == 1) /* 关闭 LED 灯 */
61 cmd = CLOSE_CMD;
62 else if(cmd == 2) /* 打开 LED 灯 */
63 cmd = OPEN_CMD;
64 else if(cmd == 3) {
65 cmd = SETPERIOD_CMD; /* 设置周期值 */
66 printf("Input Timer Period:");
67 ret = scanf("%d", &arg);
68 if (ret != 1) { /* 参数输入错误 */
69 gets(str); /* 防止卡死 */
70 }
71 }
72 ioctl(fd, cmd, arg); /* 控制定时器的打开和关闭 */
73 }
74 close(fd);
75 }
①、运行 APP 以后提示我们输入要测试的命令,输入 1 表示关闭定时器、输入 2 表示打开定时器,输入 3 设置定时器周期。
②、如果要设置定时器周期的话,需要让用户输入要设置的周期值,单位为毫秒。
第 22~24 行,命令值。
第 53~73 行, while(1)循环,让用户输入要测试的命令,然后通过第 72 行的 ioctl 函数发送给驱动程序。如果是设置定时器周期命令 SETPERIOD_CMD,那么 ioctl 函数的 arg 参数就是用户输入的周期值。
四、运行测试
1.编译驱动程序和测试AP
编译成功以后就会生成一个名为“ timer.ko”的驱动模块文件。
编译成功以后就会生成 timerApp 这个应用程序。
2.运行测试
根据提示输入指令及周期,观察LED的交替亮变化即可。
五、总结
本节笔记主要学习Linux内核定时器的驱动开发,主要包括内核时间管理和定时器、硬件原理图分析【LED】、驱动开发和测试。最重要的内容为定时器驱动开发部分。
本文为参考正点原子开发板配套教程整理而得,仅用于学习交流使用,不得用于商业用途。
相关文章:

Linux学习第21天:Linux内核定时器驱动开发: 流淌的时间长河
Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 在人类的发展进化中,时间是一个非常重要神秘的物质量。任何事物都是在时间的长河中流淌发生、发展、变化。我们进行驱动开发中对时间的定义和使用也是…...
Centos服务在服务器重启后自启
以Dolphin为例 打开rc.local文件以编辑: sudo vi /etc/rc.d/rc.local在文件中添加您的启动命令。在您的情况下,要添加的命令如下: sh /opt/dolphinscheduler/zookeeper/bin/zkServer.sh start sh /opt/dolphinscheduler/dolphinscheduler/…...

慢性疼痛治疗服务公司Kindly MD申请700万美元纳斯达克IPO上市
来源:猛兽财经 作者:猛兽财经 猛兽财经获悉,慢性疼痛治疗服务公司Kindly MD近期已向美国证券交易委员会(SEC)提交招股书,申请在纳斯达克IPO上市,股票代码为(KDLY),Kindly MD计划通过…...

代码随想录 Day6 哈希 LeetcodeT454 四数之和II T383赎金信 T15 三数之和 T18 四数之和
本文代码思路来源于: 代码随想录 前言 希望大家在刷这部分题的时候先熟悉熟悉哈希结构的基本常用api,比较方便理解. LeetCode T454 四数之和 题目链接:454. 四数相加 II - 力扣(LeetCode) 题目思路 暴力解法仍然是遍历四个数组解决此题, 哈希的思路有…...

干货速来|教你如何撰写毕业论文
撰写毕业论文对于正常大学毕业至关重要。毕业论文是对学生在大学期间所学知识的综合运用和深入研究的体现,也是对学术能力和独立思考能力的考验。 撰写毕业论文的过程需要学生投入大量的时间和精力,包括选题、文献综述、研究方法选择、数据收集和分析、…...

【ROS 2】-2 话题通信
飞书原文链接: Docs...

Unity之NetCode多人网络游戏联机对战教程(2)--简单实现联机
文章目录 1.添加基本组件2.创建NetworkManager组件3.创建Player4.创建地面5.创建GameManager6.编译运行7. 测试联机后话 1.添加基本组件 NetworkManagerPlayerScene 2.创建NetworkManager组件 创建一个空物体,命名为NetworkManager 选择刚刚创建的NetworkManager…...
makdown文法
这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…...

新手程序员怎么接单?
程序员如何在自己年富力强的时候,最大化发挥自己的能力?将超能力转化为“钞能力”? 有人还在苦哈哈当老黄牛,一身使不完的牛劲,有人已经另辟蹊径,开创了自己的一片致富小天地。 接单找兼职,就…...

接口测试——接口协议抓包分析与mock_L2
目录: 抓包工具charles抓包工具fiddler抓包工具证书配置app抓包实战练习接口测试实战练习 1.抓包工具charles 工具介绍 支持 SSL 代理支持流量控制支持重发网络请求,方便后端调试支持修改网络请求参数支持网络请求的截获并动态修改可以自动将 json 或…...

Seata入门系列【1】安装seata 1.7.1+nacos 2.1.1
1 介绍 Seata 是一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式,为用户打造一站式的分布式解决方案。 Github: https://github.com/seata/seata 官方文档:h…...

2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题
2023年职业院校技能大赛中职组----大数据应用与服务赛项任务书试题 模块一:数据库系统运维(25分)任务一:数据库系统搭建(10分)任务二:房源数据库系统运维(15分) 模块二&a…...
产品经理的职业前景怎么样?一文为你全面解答!
随着科技的迅速发展和市场竞争的日益激烈,产品经理这个职业变得越来越炙手可热。产品经理负责一款产品的全生命周期管理,从需求收集到设计、开发、测试、发布,再到市场推广和用户反馈,都需要产品经理参与决策。因此,这…...

【深度学习】图像去噪(2)——常见网络学习
【深度学习】图像去噪 是在 【深度学习】计算机视觉 系列文章的基础上,再次针对深度学习(尤其是图像去噪方面)的基础知识有更深入学习和巩固。 1 DnCNN 1.1 网络结构 1.1.1 残差学习 1.1.2 Batch Normalization (BN) 1.1.2.1 背景和目标…...

八大排序详解
目录 1.排序的概念及应用 1.1 排序的概念 1.2 排序的应用 1.3 常见的排序算法 2.常见排序算法的实现 2.1 直接插入排序 2.1.1 基本思想 2.1.2 动图解析 2.1.3 排序步骤(默认升序) 2.1.4 代码实现 2.1.5 特性总结 2.2 希尔排序 2.2.1 基本思…...

自定义热加载:如何不停机实现核心代码更新
文章目录 1. 常见的几种实现代码热更新的几种方式对于开发环境我们可以使用部署环境1. 使用 Arthas 的 redefine 命令来加载新的 class 文件2. 利用 URLClassLoader 动态加载3. 通过Java的Instrumentation API 也是可以实现的 2. 实现1. ClassScanner扫描目录和加载类2. 定时任…...

Spring Cloud Alibaba Nacos 2.2.3 (2) - 单机版启动 (winodows 和 linux )
Nacos 2.2.3 (1) - 下载与数据库配置 参考下载与数据库配置 启动服务器 执行 nacos-server-2.2.3\bin 下的startup.sh或者startup.cmd (根据不同系统) windows 下nacos 单机启动 方式一: 1,打开cmd 2,cd 到nacos-s…...

VB从资源文件中播放wav音乐文件
Private Const SND_SYNC &H0 Private Const SND_MEMORY &H4 API函数 Private Declare Function sndPlaySoundFromMemory Lib "winmm.dll" Alias "sndPlaySoundA" (lpszSoundName As Any, ByVal uFlags As Long) As Long 音乐效果请“单击” Pr…...

web:[HCTF 2018]WarmUp
题目 点进页面,页面只有一张滑稽脸,没有其他的提示信息 查看网页源代码,发现source.php,尝试访问一下 跳转至该页面,页面显示为一段php代码,需要进行代码审计 <?phphighlight_file(__FILE__);class emm…...

程序开发常用在线工具汇总
菜鸟工具# https://c.runoob.com/ 编码# ASCII码# https://www.habaijian.com/ 在线转换# https://www.107000.com/T-Ascii/http://www.ab126.com/goju/1711.html Base64# 在线转换# https://www.qqxiuzi.cn/bianma/base64.htmhttp://www.mxcz.net/tools/Unicode.aspx …...

XCTF-web-easyupload
试了试php,php7,pht,phtml等,都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接,得到flag...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...