第九周预习报告
文章目录
- 第九周预习报告
- 学习内容
- AI 对学习内容的总结
- 章节概述
- 内容总结
- 对知识总结的反思
- 思维导图
- 基于AI的学习
- 知识点1:系统调用
- 知识点2:进程控制
- 学习实践过程遇到的问题与解决方式
- 问题1:`fork()` 调用后,子进程和父进程同时运行导致输出混乱
- 问题2:`exec()` 调用失败,程序无法执行新程序
- 问题3:`open()` 系统调用失败,无法打开文件
- 问题4:`wait()` 调用后,父进程无法正确捕获子进程的退出状态
- 问题5:环境变量传递失败,子进程无法获取正确的环境变量
- 参考资料
第九周预习报告
学习内容
- Head First C 第9章
AI 对学习内容的总结
章节概述
- 本章主要介绍进程和系统调用的概念,学习如何在自己的代码内部使用其他程序,学会如何使用系统服务来创建和控制进程。使程序能够访问电子邮件、Web以及其他任何安装的工具。
内容总结
-
系统调用:
- 定义:系统调用是用户程序与操作系统内核之间的接口,允许用户程序请求操作系统执行特定的任务。
- 常见系统调用:
open():打开文件。read():从文件中读取数据。write():将数据写入文件。close():关闭文件。fork():创建一个新进程。exec():执行一个新程序。wait():等待子进程结束。exit():终止当前进程。
- 工作原理:当用户程序调用一个系统调用时,CPU会从用户模式切换到内核模式,内核执行相应的操作,完成后返回结果,CPU再切换回用户模式。
-
进程控制:
- 进程:进程是操作系统进行资源分配和调度的基本单位,每个进程都有自己的地址空间、文件描述符、环境变量等。
- 创建进程:
fork():创建一个新进程,新进程是调用进程的副本,两者几乎完全相同,但有一个唯一的区别:fork()返回值不同。在父进程中返回子进程的PID,在子进程中返回0。
- 执行新程序:
exec():有一系列函数(如execl()、execlp()、execle()、execv()、execvp()、execvpe()),用于替换当前进程的地址空间,使其开始执行一个新程序。
- 等待子进程:
wait():父进程调用wait()等待子进程结束,wait()会阻塞父进程直到子进程结束。
- 终止进程:
exit():终止当前进程,可以传递一个退出状态码给父进程。
-
环境变量传递:
- 定义:环境变量是操作系统提供的一种机制,用于在进程之间传递配置信息。
- 传递方式:子进程会继承父进程的环境变量,可以通过
exec()系列函数传递新的环境变量。
-
错误处理:
- 返回值:大多数系统调用都有一个返回值,成功时返回一个有意义的值,失败时返回一个错误码(通常是负数)。
- errno:全局变量
errno用于存储系统调用的错误代码,可以通过strerror()函数将错误代码转换为人类可读的字符串。#include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h>int main() {int fd = open("nonexistent_file.txt", O_RDONLY);if (fd == -1) {fprintf(stderr, "Error opening file: %s\n", strerror(errno));return 1;}close(fd);return 0; }
-
RSS订阅:
- 定义:RSS(Really Simple Syndication)是一种用于发布经常更新的内容的标准格式,如博客文章、新闻等。
- 实现:通过系统调用读取RSS源,解析XML数据,提取所需信息。
#include <stdio.h> #include <curl/curl.h>size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) {size_t written = fwrite(ptr, size, nmemb, stream);return written; }int main() {CURL *curl;FILE *file;CURLcode res;curl_global_init(CURL_GLOBAL_DEFAULT);curl = curl_easy_init();if(curl) {file = fopen("rss_feed.xml", "wb");curl_easy_setopt(curl, CURLOPT_URL, "http://example.com/rss.xml");curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);curl_easy_setopt(curl, CURLOPT_WRITEDATA, file);res = curl_easy_perform(curl);if(res != CURLE_OK) {fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));}fclose(file);curl_easy_cleanup(curl);}curl_global_cleanup();return 0; }
-
父子进程关系:
- 父子关系:通过
fork()创建的子进程是父进程的子进程,子进程可以调用getppid()获取父进程的PID。#include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程printf("Child process: PID = %d, PPID = %d\n", getpid(), getppid());execlp("/bin/ls", "ls", "-l", NULL);} else {// 父进程printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);wait(NULL); // 等待子进程结束printf("Child process finished\n");}return 0; }
- 父子关系:通过
对知识总结的反思
-
系统调用:
- 系统调用是用户程序与操作系统内核之间的桥梁,通过系统调用可以执行各种底层操作,如文件操作、进程控制等。
- 在实际编程中,需要仔细检查每个系统调用的返回值,以确保调用成功,并处理可能出现的错误。
-
进程控制:
- 进程控制是操作系统管理进程生命周期的关键部分,通过
fork()和exec()可以创建和执行新的进程。 - 在使用
fork()和exec()时,需要注意父子进程的关系,确保程序逻辑的正确性。
- 进程控制是操作系统管理进程生命周期的关键部分,通过
-
环境变量传递:
- 环境变量是进程之间传递配置信息的重要机制,子进程会继承父进程的环境变量。
- 在调用
exec()系列函数时,可以通过参数传递新的环境变量。
-
错误处理:
- 错误处理是确保程序健壮性的关键,通过检查系统调用的返回值和使用
errno,可以有效地处理错误。
- 错误处理是确保程序健壮性的关键,通过检查系统调用的返回值和使用
-
RSS订阅:
- RSS订阅是一个实际应用的例子,展示了如何使用系统调用和网络编程来获取和处理外部数据。
- 通过CURL库,可以方便地实现HTTP请求和数据下载。
思维导图
mindmap本周学习内容进程和系统调用章节概述系统调用定义常见系统调用openreadwritecloseforkexecwaitexit进程控制进程创建进程fork执行新程序exec等待子进程wait终止进程exit环境变量传递定义传递方式错误处理返回值errnoRSS订阅定义实现使用CURL库解析XML数据父子进程关系父子关系getppid重点内容系统调用定义常见系统调用openreadwritecloseforkexecwaitexit进程控制进程创建进程fork执行新程序exec等待子进程wait终止进程exit环境变量传递定义传递方式错误处理返回值errnoRSS订阅定义实现使用CURL库解析XML数据父子进程关系父子关系getppid

基于AI的学习
知识点1:系统调用
AI: 举一个常见的系统调用例子。
我: 打开文件是一个常见的系统调用。当程序想要读取或写入文件时,它会调用 open() 系统调用。这个调用会请求操作系统打开指定的文件,并返回一个文件描述符,程序可以使用这个文件描述符进行后续的读写操作。
AI: 系统调用 fork() 和 exec() 有什么区别?
我: fork() 和 exec() 是两个不同的系统调用,它们分别用于不同的目的。
fork()用于创建一个新的进程。新进程是调用进程的副本,具有相同的代码段、数据段和堆栈段,但有自己的独立内存空间。fork()返回一个值,如果返回值为0,则表示当前进程是子进程;如果返回值大于0,则表示当前进程是父进程,返回值是子进程的PID。exec()用于在当前进程中加载并运行一个新的程序。exec()有多个变种,如execl()、execlp()、execle()、execv()、execvp()和execvpe(),它们的主要区别在于参数的传递方式。调用exec()之后,当前进程的代码段、数据段和堆栈段会被新程序的代码段、数据段和堆栈段替换。
AI: wait() 系统调用的作用是什么?
我: wait() 系统调用用于父进程等待子进程结束。父进程调用 wait() 会阻塞,直到一个子进程结束。wait() 返回子进程的PID,并且可以通过返回值和 wait() 的参数来获取子进程的退出状态。
AI: 如何处理系统调用的错误?
我: 处理系统调用的错误通常涉及以下几个步骤:
- 检查系统调用的返回值。大多数系统调用在成功时返回一个有意义的值,而在失败时返回一个错误码(通常是负数)。
- 如果系统调用失败,检查全局变量
errno以获取具体的错误代码。 - 使用
strerror()函数将错误代码转换为人类可读的错误信息,并进行适当的错误处理,如打印错误信息、记录日志或采取其他补救措施。
AI: 举一个处理 open() 系统调用错误的例子。
我: 当然,以下是一个处理 open() 系统调用错误的示例代码:
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>int main() {int fd = open("nonexistent_file.txt", O_RDONLY);if (fd == -1) {fprintf(stderr, "Error opening file: %s\n", strerror(errno));return 1;}close(fd);return 0;
}
在这个例子中,如果 open() 调用失败,fd 将被设置为 -1,程序会检查 errno 并使用 strerror() 函数将错误代码转换为错误信息,然后打印错误信息并返回1表示程序异常退出。
知识点2:进程控制
AI: 什么是进程?
我: 进程是操作系统进行资源分配和调度的基本单位。每个进程都有自己的地址空间、文件描述符、环境变量等。进程可以包含一个或多个线程,每个线程共享进程的资源。
AI: fork() 系统调用的返回值有什么含义?
我: fork() 系统调用的返回值有三种可能:
- 如果
fork()成功,它会在父进程中返回子进程的PID(进程标识符),在子进程中返回0。 - 如果
fork()失败,它会返回-1,并设置全局变量errno以指示具体的错误原因。
AI: exec() 系统调用的变种有哪些?
我: exec() 系统调用有多个变种,它们的主要区别在于参数的传递方式:
execl(): 以固定数量的参数调用新程序。execlp(): 类似于execl(),但会在环境变量PATH中查找可执行文件。execle(): 类似于execl(),但允许传递环境变量。execv(): 以数组形式传递参数。execvp(): 类似于execv(),但会在环境变量PATH中查找可执行文件。execvpe(): 类似于execvp(),但允许传递环境变量。
AI: wait() 系统调用的参数和返回值是什么?
我: wait() 系统调用的原型如下:
pid_t wait(int *status);
- 参数
status是一个指向整数的指针,用于接收子进程的退出状态。如果不需要获取退出状态,可以将status设为NULL。 - 返回值是子进程的PID。如果没有子进程结束,
wait()会阻塞父进程。如果wait()失败,它会返回-1,并设置全局变量errno以指示具体的错误原因。
AI: 举一个使用 fork() 和 exec() 的示例。
我: 当然,以下是一个使用 fork() 和 exec() 的示例代码:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程printf("Child process: PID = %d, PPID = %d\n", getpid(), getppid());execlp("/bin/ls", "ls", "-l", NULL);fprintf(stderr, "Failed to execute ls\n");return 1;} else {// 父进程printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);wait(NULL); // 等待子进程结束printf("Child process finished\n");}return 0;
}
在这个例子中,父进程调用 fork() 创建一个子进程。子进程调用 execlp() 执行 /bin/ls 命令,列出当前目录的详细信息。父进程调用 wait() 等待子进程结束,然后打印一条消息表示子进程已经结束。
学习实践过程遇到的问题与解决方式
问题1:fork() 调用后,子进程和父进程同时运行导致输出混乱
描述:在使用 fork() 创建子进程后,子进程和父进程同时运行,导致输出混乱,难以区分哪个输出来自哪个进程。
解决方式:
- 使用
sleep()临时解决:#include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程sleep(1); // 让子进程稍微延迟一下printf("Child process: PID = %d, PPID = %d\n", getpid(), getppid());execlp("/bin/ls", "ls", "-l", NULL);} else {// 父进程printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);wait(NULL); // 等待子进程结束printf("Child process finished\n");}return 0; } - 使用
wait()确保子进程先结束:#include <stdio.h> #include <unistd.h> #include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程printf("Child process: PID = %d, PPID = %d\n", getpid(), getppid());execlp("/bin/ls", "ls", "-l", NULL);} else {// 父进程wait(NULL); // 等待子进程结束printf("Parent process: PID = %d, Child PID = %d\n", getpid(), pid);printf("Child process finished\n");}return 0; }
问题2:exec() 调用失败,程序无法执行新程序
描述:在调用 exec() 系列函数时,程序无法成功执行新程序,导致程序挂起或报错。
解决方式:
- 检查路径和文件名:
确保提供的路径和文件名是正确的。如果使用execlp()或execvp(),确保环境变量PATH中包含了可执行文件的路径。 - 检查错误信息:
使用perror()或strerror(errno)打印详细的错误信息。#include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程execlp("/bin/ls", "ls", "-l", NULL);perror("Failed to execute ls"); // 打印错误信息return 1;} else {// 父进程wait(NULL); // 等待子进程结束printf("Child process finished\n");}return 0; }
问题3:open() 系统调用失败,无法打开文件
描述:在调用 open() 系统调用时,无法打开指定的文件,导致程序出错。
解决方式:
- 检查文件路径和权限:
确保文件路径是正确的,并且当前用户有权限访问该文件。 - 检查错误信息:
使用perror()或strerror(errno)打印详细的错误信息。#include <stdio.h> #include <unistd.h> #include <errno.h> #include <string.h>int main() {int fd = open("nonexistent_file.txt", O_RDONLY);if (fd == -1) {fprintf(stderr, "Error opening file: %s\n", strerror(errno));return 1;}close(fd);return 0; }
问题4:wait() 调用后,父进程无法正确捕获子进程的退出状态
描述:在调用 wait() 系统调用后,父进程无法正确捕获子进程的退出状态,导致程序逻辑出错。
解决方式:
使用 WIFEXITED 和 WEXITSTATUS 宏:
使用 WIFEXITED 检查子进程是否正常退出,使用 WEXITSTATUS 获取子进程的退出状态。
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程execlp("/bin/ls", "ls", "-l", NULL);perror("Failed to execute ls");return 1;} else {// 父进程int status;pid_t child_pid = wait(&status);if (WIFEXITED(status)) {printf("Child process %d exited with status %d\n", child_pid, WEXITSTATUS(status));} else {printf("Child process %d terminated abnormally\n", child_pid);}}return 0;
}
问题5:环境变量传递失败,子进程无法获取正确的环境变量
描述:在使用 exec() 系列函数时,子进程无法获取正确的环境变量,导致程序出错。
解决方式:
检查环境变量的传递方式:
确保在调用 exec() 系列函数时正确传递了环境变量。
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int main() {pid_t pid = fork();if (pid < 0) {fprintf(stderr, "Fork failed\n");return 1;} else if (pid == 0) {// 子进程char *new_env[] = {"PATH=/usr/bin:/bin", "MY_VAR=value", NULL};execle("/bin/ls", "ls", "-l", NULL, new_env);perror("Failed to execute ls");return 1;} else {// 父进程wait(NULL); // 等待子进程结束printf("Child process finished\n");}return 0;
}
参考资料
- HeadFirstC嗨翻C语言
- 通义千问
- Linux System Calls
- Process Control in Linux
- Error Handling in C
- 课程 mindmap
- Mermaid Live Editor
相关文章:
第九周预习报告
文章目录 第九周预习报告学习内容AI 对学习内容的总结章节概述内容总结 对知识总结的反思思维导图基于AI的学习知识点1:系统调用知识点2:进程控制 学习实践过程遇到的问题与解决方式问题1:fork() 调用后,子进程和父进程同时运行导…...
【分享】这篇教程助力你成为 JavaScript 糕手!(四)
第四章:运算符与表达式 4.1 算术运算符 加法运算符():用于数字相加,如console.log(5 3);结果为8。 当用于字符串时,它表示字符串拼接。例如console.log(‘Hello’ ‘world’);输出Hello world。如果一个操…...
双亲委派模型的破坏
双亲委派模型的第一次“被破坏”其实发生在双亲委派模型出现之前--即JDK1.2发布之前。由于双亲委派模型是在JDK1.2之后才被引入的,而类加载器和抽象类java.lang.ClassLoader则是JDK1.0时候就已经存在,面对已经存在 的用户自定义类加载器的实现代码,Java设计者引入双亲委派模…...
Android关机流程知多少?
在 Android 中,关机流程涉及系统各个组件的协同工作,确保设备在断电之前能够安全地关闭所有活动并保存数据。以下是 Android 系统中关机流程的详细介绍: 1. 用户触发关机请求 关机流程由用户的操作触发,通常有以下几种方式&#…...
深入理解指针end(总结篇)
如果有不会的智识点,请移动到博主前四篇指针博客! 可以当一个指针智商检阅博客看。 看看你是否掌握了这些知识 1:内存,指针变量 内存单元的编号地址指针; 指针变量和其他变量没有区别,指针变量是来存放…...
C# 程序暂停的两种方式
C# 程序暂停的两种方式:EventWaitHandle 与 volatile bool pause 在C#中,线程控制是多线程编程的重要组成部分,其中实现暂停的需求经常出现。本文将详细探讨使用EventWaitHandle和设置volatilebool来实现线程暂停的不同方式,它们…...
【LeetCode】【算法】160.相交链表
Leetcode 160. 相交链表 题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 思路 AB,一个指针,访问完A访问B;另一个指针&#…...
光伏破局 引领能源革命
为进一步推进商业信用体系建设,促进企业诚实守信经营,面向企业普及诚信与品牌建设的意义,指导企业加强诚信品牌建设,提升其整体竞争力,“崛起的民族品牌”专题系列节目以诚信为内涵,在全国范围内遴选出有行…...
Jenkins声明式Pipeline流水线语法示例
系列文章目录 docker搭建Jenkins2.346.3版本及常用工具集成配置(ldap、maven、ansible、npm等) docker安装低版本的jenkins-2.346.3,在线安装对应版本插件失败的解决方法 文章目录 系列文章目录jenkins流水线基础1、pipeline1.1、什么是pipeline?1.2、为什么使用pi…...
互联网技术净土?原生鸿蒙开启全新技术征程
鸿蒙生态与开发者的崭新机会 HarmonyOS NEXT承载着华为对未来操作系统的深刻理解,如今已发展为坚实的数字底座。它不仅在技术层面取得了全面突破,还在中国操作系统市场中站稳了脚跟。 当前,HarmonyOS NEXT的代码行数已超过1.1亿,…...
关于Django 模型字段 `choices`自定义数据类型的枚举——补充
文章目录 1. 处理 datetime 类型的 choices2. 处理 time 类型的 choices3. 处理 Decimal 类型的 choices4. 处理 UUID 类型的 choices5. 处理 float 类型的 choices 在 Choices 类的基础上扩展,可以将 choices 与特定数据类型(如 date 或 datetime&a…...
CAP理论的延申--BASE理论
上一篇文章我简单介绍了一下什么是CAP理论,本篇文章讲解一下随着技术的演变,CAP理论是如何发展为BASE理论的。 CAP理论回顾 首先我们回顾一下CAP理论,CAP理论指得是分布式系统发生网络等故障时,不同节点之间无法同步数据…...
【傻呱呱】phpMyAdmin怎样给特定用户授权特定数据库权限?
前期准备 phpMyAdmin数据库(MySQL) END...
『VUE』21. 组件注册(详细图文注释)
目录 组件注册局部注册全局注册全局注册示例总结 欢迎关注 『VUE』 专栏,持续更新中 欢迎关注 『VUE』 专栏,持续更新中 组件注册 组件注册有两种方式:全局注册和局部注册。全局注册只需要注册依次,其他组件可以直接调用无需再次像局部注册一…...
如何产看SQL 查询的执行时间
要查看 SQL 查询的执行时间,尤其是毫秒级别,可以使用以下几种方法: 方法 1:使用 SET STATISTICS TIME 查看执行时间 SET STATISTICS TIME 会显示执行时间的详细信息,包括 CPU 时间和总耗时。启用后,SQL S…...
计算机网络——路由器构成
算路由表是分布式去算——你算你的,我算我的 输出队列非先来先传 调度发生在哪里 缓存队列一般是应对——来数据方向的速度过快问题...
架构师之路-学渣到学霸历程-48
实现域名跳转的实验 今天继续还是分享域名跳转的实验;继续整,看看效果 意思就是你本来访问www.liangjiawei.net的网站然后跳转到blog.liangjiawei.net的网站 1、基础的环境部署 安装好nginx(这里最好的就是干净的环境)创建两个…...
HappyChart——一款简单好用的专业绘图软件
HappyChart是一款新出的专业绘图软件,灵感来自于类PS软件,它是以图层的方式进行绘图。相比与Excel图表或其他专业绘图软件,HappyChart界面简洁明了,操作简单,没有复杂的选项,它只调整绘图相关参数即可实时展…...
【Linux】进程信号全攻略(二)
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 再谈信号的捕捉 🦋 关于信号捕捉的细节部分(sigaction函数) 二:🔥 穿插话题 - 操作系统是怎么运…...
redis用法(二)
文章目录 02-redis数据类型篇生产环境下的redis实况图 1.全局命令redis数据存储格式set设置k-v查看当前redis的key的数量危险命令,新手请在于超老师陪同下执行为什么危险?如何正确搜索redis的key 查看库下有多少个key查询redis库信息切换redis库查看key是…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能
1. 开发环境准备 安装DevEco Studio 3.1: 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK 项目配置: // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
华硕电脑,全新的超频方式,无需进入BIOS
想要追求更佳性能释放 或探索更多可玩性的小伙伴, 可能会需要为你的电脑超频。 但我们常用的不论是BIOS里的超频, 还是Armoury Crate奥创智控中心超频, 每次调节都要重启,有点麻烦。 TurboV Core 全新的超频方案来了 4不规…...
RK3568项目(七)--uboot系统之外设与PMIC详解
目录 一、引言 二、按键 ------>2.1、按键种类 ------------>2.1.1、RESET ------------>2.1.2、UPDATE ------------>2.1.3、PWRON 部分 ------------>2.1.4、RK809 PMIC ------------>2.1.5、ADC按键 ------------>2.1.6、ADC按键驱动 ------…...
