Linux第67步_linux字符設備驅動_注冊和注銷

1、字符設備注冊與注銷的函數原型”

/*字符設備注冊的函數原型*/

static inline int register_chrdev(unsigned int major,\

????????????????????????????????? const char *name,? \

???????????????????????????????? ?const struct file_operations *fops)

/*

major:主設備號,Limnux下每個設備都有一個設備號,設備號分為主設備號和次設備號兩部分。

name:設備名字,指向一串字符串。

fops:結構體file_operations類型指針,指向設備的操作函數集合變量。

*/

/*字符設備注銷的函數原型*/

static inline void unregister_chrdev(unsigned int major,\

?????????????????????????? ??????????const char *name)

/*

major:主設備號,Limnux下每個設備都有一個設備號,設備號分為主設備號和次設備號兩部分。

name:設備名字,指向一串字符串。

*/

2、Linux設備號

1)、使用設備號的原因:為了方便管理,Linux 中每個設備都有一個設備號。

2)、設備號的組成

Linux設備號是由主設備號和次設備號兩部分組成;

主設備號表示某一個具體的驅動;

次設備號表示使用這個驅動的各個設備。

Linux使用“dev_t的數據類型”表示設備號;

dev_t的數據類型”定義在文件“include/linux/types.h”里面,定義如下:

typedef __u32 __kernel_dev_t;

//為“__u32”起個別名叫“__kernel_dev_t”

typedef __kernel_dev_t dev_t;

//為“__kernel_dev_t”起個別名叫“dev_t”

由此可見,dev_t是 umsigned int類型,是一個32位的數據類型。這個32位的數據就是Linux設備號,它是由“主設備號”和“次設備號”兩部分構成,其中高12位為“主設備號”,低20位為“次設備號”。因此,Linux系統中主設備號范圍為0~4095,所以,大家在選擇主設備號的時候一定不要超過這個范圍

在文件“include/linux/kdev_t.h”中提供了幾個關于設備號的操作函數(本質是宏),如下所示:

#define MINORBITS 20???????? //定義“次設備號”占據低20位

#define MINORMASK ((1U << MINORBITS) - 1) //定義“次設備號”的掩碼值

#define MAJOR(dev) ((unsigned int) ((dev) >> MINORBITS))

//輸入參數dev為“Linux設備號”

//將dev右移20位得到“主設備號”

#define MINOR(dev) ((unsigned int) ((dev) & MINORMASK))

//輸入參數dev為“Linux設備號”

//將dev與0xFFFFF相與后得到“次設備號”

#define MKDEV(ma,mi) (((ma) << MINORBITS) | (mi))

//輸入參數ma為“主設備號”

//輸入參數mi為“次設備號”

//將ma左移20位,再與mi相或,就得到“Linux設備號”

設備號的申請函數

int alloc_chrdev_region(dev_t *dev,\

??????????????????????? unsigned baseminor,\

??????????????????????? unsigned count,\

??????????????????????? const char *name)

//dev:保存申請到的設備號

//baseminor:次設備號的起始地址

//alloc_chrdev_region可以申請一段連續的多個“設備號”,這些“設備號”的“主設備號”是一樣的,但是“次設備號”不同。“次設備號”以baseminor為起始值開始遞增。通常baseminor的值為0。

//count:要申請的設備號數量;

// name:表示“設備名字”

設備號的釋放函數

void unregister_chrdev_region(dev_t from, unsigned count)

// from:要釋放的設備號;

// count:表示從from開始,要釋放的設備號數量。

3、字符設備加載,注冊,注銷和卸載的一般模板

#define xxx_MAJOR?? 200

//定義主設備號

//靜態分配設備號:在串口輸入“cat/proc/devices”查詢當前已用的主設備號

//然后使用一個“沒有被使用的設備號”作為該設備的的主設備號

#define xxx_NAME?? "xxxName"? //定義設備的名字。

const struct file_operations xxx_fops = {};

//聲明一個file_operations結構變量

/*驅動入口函數 */

static int? __init xxx_init(void)

{

??? int ret;

??? ret = register_chrdev(xxx_MAJOR, xxx_NAME, &xxx_fops);

//注冊字符設備驅動

//xxx_MAJOR為主設備號,采用宏xxx_NAME定義設備名字

//xxx_fops是設備的操作函數集合,它是file_operations結構變量

??? if (ret < 0) {

?????? pr_err("xxx_init is failed!!!\r\n");

?????? return ret;

??? }

??? else pr_err("xxx_init is ok!!!\r\n");

?? return 0;

}

/*驅動出口函數 */

static void __exit xxx_exit(void)

{

?? /*出口函數具體內容 */

??? unregister_chrdev(xxx_MAJOR, xxx_NAME);

????//注銷字符設備驅動

//xxx_MAJOR為主設備號,采用宏xxx_NAME定義設備名字

}

module_init(xxx_init); //聲明xxx_init()為驅動入口函數

module_exit(xxx_exit); //聲明xxx_exit()為驅動出口函數

4、查看linux-5.4.31”中的設備注冊和注銷

打開虛擬機上“VSCode”,點擊“文件”,點擊“打開文件夾”,點擊“zgq”,點擊“linux”,點擊“atk-mp1”,點擊“linux”,點擊“my_linux”,點擊“linux-5.4.31”,見下圖:

點擊“確定

點擊“查看”,點擊“搜索”,輸入“register_chrdev

假如我們點擊的是“rtlx-cmp.c”,見下圖:

rtlx-cmp.c”程序如下:

#include <linux/device.h>

#include <linux/fs.h>

#include <linux/err.h>

#include <linux/wait.h>

#include <linux/sched.h>

#include <linux/smp.h>

#include <asm/mips_mt.h>

#include <asm/vpe.h>

#include <asm/rtlx.h>

static int major;//major:設備號

/*從字面意思看,是一個中斷*/

static void rtlx_interrupt(void)

{

??? int i;

??? struct rtlx_info *info;

??? struct rtlx_info **p = vpe_get_shared(aprp_cpu_index());

??? if (p == NULL || *p == NULL)

?????? return;

??? info = *p;

??? if (info->ap_int_pending == 1 && smp_processor_id() == 0) {

?????? for (i = 0; i < RTLX_CHANNELS; i++) {

?????????? wake_up(&channel_wqs[i].lx_queue);

?????????? wake_up(&channel_wqs[i].rt_queue);

?????? }

?????? info->ap_int_pending = 0;

??? }

}

/*從字面看是講中斷堆棧指針*/

void _interrupt_sp(void)

{

??? smp_send_reschedule(aprp_cpu_index());

}

/*入口函數初始化*/

int __init rtlx_module_init(void)

{

??? struct device *dev;

??? int i, err;

??? if (!cpu_has_mipsmt) {

?????? pr_warn("VPE loader: not a MIPS MT capable processor\n");

?????? return -ENODEV;

??? }

??? if (num_possible_cpus() - aprp_cpu_index() < 1) {

?????? pr_warn("No TCs reserved for AP/SP, not initializing RTLX.\n"

?????????? "Pass maxcpus=<n> argument as kernel argument\n");

?????? return -ENODEV;

??? }

??? major = register_chrdev(0, RTLX_MODULE_NAME, &rtlx_fops);

//注冊字符設備驅動

???//0為主設備號,采用宏RTLX_MODULE_NAME定義設備名字

???//rtlx_fops是設備的操作函數集合,它是file_operations結構變量

??? if (major < 0) {//讀取主設備號小于0,則打印錯誤信息

?????? pr_err("rtlx_module_init: unable to register device\n");

?????? return major;

??? }

??? /* initialise the wait queues */

??? for (i = 0; i < RTLX_CHANNELS; i++) {

?????? init_waitqueue_head(&channel_wqs[i].rt_queue);

???????//初始化等待隊列頭

?????? init_waitqueue_head(&channel_wqs[i].lx_queue);

???????//初始化等待隊列頭

?????? atomic_set(&channel_wqs[i].in_open, 0);//狀態重置

?????? mutex_init(&channel_wqs[i].mutex);//初始化互斥體

?????? dev = device_create(mt_class, NULL, MKDEV(major, i), NULL,

????????????? ??? "%s%d", RTLX_MODULE_NAME, i);

//創建設備, major為主設備號,i為次設備號

//參數mt_class表示該設備位于mt_class類下面

// parent為NULL表示沒有父設備

//將major左移20位,再與i相或,就得到“Linux設備號”

//drvdata為NULL表示沒有使用設備文件

//采用RTLX_MODULE_NAME宏定義指向字符串表示設備名

?????? if (IS_ERR(dev)) {

?????????? while (i--)

????????????? device_destroy(mt_class, MKDEV(major, i));

??????????????//刪除創建的設備

??????????????//參數mt_class是設備所處的類,參數i是設備號

?????????? err = PTR_ERR(dev);

?????????? goto out_chrdev;

?????? }

??? }

??? /* set up notifiers */

??? rtlx_notify.start = rtlx_starting;

??? rtlx_notify.stop = rtlx_stopping;

??? vpe_notify(aprp_cpu_index(), &rtlx_notify);

??? if (cpu_has_vint) {

?????? aprp_hook = rtlx_interrupt;

??? } else {

?????? pr_err("APRP RTLX init on non-vectored-interrupt processor\n");

?????? err = -ENODEV;

?????? goto out_class;

??? }

??? return 0;

out_class:

??? for (i = 0; i < RTLX_CHANNELS; i++)

?????? device_destroy(mt_class, MKDEV(major, i));

???????//刪除創建的設備

???????//參數mt_class是要刪除的設備所處的類,參數i是要刪除的設備號

out_chrdev:

??? unregister_chrdev(major, RTLX_MODULE_NAME);

???//注銷字符設備驅動

???//major為主設備號,采用宏RTLX_MODULE_NAME定義設備

??? return err;

}

/*出口函數初始化*/

void __exit rtlx_module_exit(void)

{

??? int i;

??? for (i = 0; i < RTLX_CHANNELS; i++)

?????? device_destroy(mt_class, MKDEV(major, i));

?????//刪除創建的設備

?????//參數mt_class是要刪除的設備所處的類,參數i是要刪除的設備號

??? unregister_chrdev(major, RTLX_MODULE_NAME);

???//注銷字符設備驅動

????//major為主設備號,采用宏RTLX_MODULE_NAME定義設備名字

??? aprp_hook = NULL;

}

5、編寫“字符設備驅”動注冊與注銷的程序

1)、創建“/home/zgq/linux/Linux_Drivers/01_MyCharDevice/”目錄

輸入“cd /home/zgq/linux/Linux_Drivers/

切換到“/home/zgq/linux/Linux_Drivers/”目錄

輸入“ls”,查詢“/home/zgq/linux/Linux_Drivers/”目錄下的文件和文件夾

輸入“mkdir 01_MyCharDevice

創建“/home/zgq/linux/Linux_Drivers/01_MyCharDevice/”目錄

輸入“ls”,查詢“/home/zgq/linux/Linux_Drivers/”目錄下的文件和文件夾

輸入“cd 01_MyCharDevice/

切換到“/home/zgq/linux/Linux_Drivers/01_MyCharDevice/”目錄

輸入“pwd”獲取絕對路徑

輸入“cd /home/zgq/linux/Linux_Drivers/00_My_TestDriver/

切換到“/home/zgq/linux/Linux_Drivers/00_My_TestDriver/”目錄

輸入“ls”,查詢“/home/zgq/linux/Linux_Drivers/00_My_TestDriver/”目錄下的文件和文件夾

輸入“cp Makefile /home/zgq/linux/Linux_Drivers/01_MyCharDevice回車

拷貝“Makefile

2)、修改Makefile文件

Makefile文件內容如下:

KERNELDIR := /home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31

#使用“:=”將其后面的字符串賦值給KERNELDIR

CURRENT_PATH := $(shell pwd)

#采用“shell pwd”獲取當前打開的路徑

#使用“$(變量名)”引用“變量的值”

obj-m := MyCharDevice.o

#生成“obj-m”需要依賴“MyCharDevice.o”

build: kernel_modules

#生成“build”需要依賴“kernel_modules”

??????? @echo $(KERNELDIR)

#輸出KERNELDIR的值為“/home/zgq/linux/atk-mp1/linux/linux-5.4.31”

??????? @echo $(CURRENT_PATH)

#輸出CURRENT_PATH的值為/home/zgq/linux/Linux_Drivers/00_My_TestDriver”

??????? @echo $(MAKE)

#輸出MAKE的值為make

kernel_modules:

??????? $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

#后面的"modules"表示編譯成模塊

#“KERNELDIR”上面定義為“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目錄”

#“CURRENT_PATH”上面定義為“當前的工作目錄”

#“-C $(KERNELDIR) M=$(CURRENT_PATH) ”表示將“當前的工作目錄”切換到“指定的目錄”中

#即切換到“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”。

#M表示模塊源碼目錄

#在“make和modules”之間加入“M=$(CURRENT_PATH)”,表示切換到由“CURRENT_PATH”指定的目錄中讀取源碼,同時將其編>譯為.ko 文件

clean:

??????? $(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

#“KERNELDIR”上面定義為“/home/zgq/linux/atk-mp1/linux/my_linux/linux-5.4.31”,即“指定的工作目錄”

#“CURRENT_PATH”上面定義為“當前的工作目錄”

3)、使用VSCode創建“MyCharDevice.c文件

添加內容如下:

#include <linux/init.h>?????? //必須要包含的頭文件

#include <linux/module.h>???? //必須要包含的頭文件

#include <linux/string.h>???? //下面要用到字符串,顯然也要包含

#include <linux/kernel.h>???? //必須要包含的頭文件

#include <linux/device.h>??? ?//必須要包含的頭文件

#include <linux/fs.h>???????? //使能結構體"file_operations"

#define MyCharDevice_MAJOR 200

//定義主設備號

//可以通過串口輸入“cat /proc/devices”查詢當前已用的主設備號

#define MyCharDevice_NAME "MyCharDeviceName"

//使用MyCharDevice_NAME指向一串字符串表示設備的名字。

const struct file_operations MyCharDevice_fops = {};

//聲明file_operations結構變量MyCharDevice_fops

//它是指向設備的操作函數集合變量

/*入口函數初始化*/

static int __init MyCharDevice_init(void)

{

??? int ret = 0;

??? printk("MyCharDevice_init\r\n");

??? ret = register_chrdev(MyCharDevice_MAJOR, MyCharDevice_NAME, &MyCharDevice_fops);

??? //返回的ret=0表示字符設備驅動注冊成功

??? //主設備號為MyCharDevice_MAJOR

??? //設備名字為RTLX_MODULE_NAME宏定義

??? //MyCharDevice_fops是設備的操作函數集合

??? if (ret < 0) {

?????? pr_err("MyCharDevice_init is failed!!!\r\n");

?????? return ret;

??? }

??? else printk("ret=%d\r\n",ret);

??? return ret;

}

/*出口函數初始化*/

static void __exit MyCharDevice_exit(void)

{

??? printk("MyCharDevice_exit\r\n");

??? unregister_chrdev(MyCharDevice_MAJOR, MyCharDevice_NAME);

??? //主設備號為MyCharDevice_MAJOR的值

??? //設備名字為MyCharDevice_NAME宏定義的字符串“MyCharDeviceName”

}

module_init(MyCharDevice_init);

/*將MyCharDevice_init()指定為入口函數*/

module_exit(MyCharDevice_exit);

/*將MyCharDevice_exit()指定為出口函數*/

MODULE_AUTHOR("Zhanggong");//添加作者名字

MODULE_DESCRIPTION("This is test module!");//模塊介紹

MODULE_LICENSE("GPL");//LICENSE采用“GPL協議”

MODULE_INFO(intree,"Y");

//去除顯示“loading out-of-tree module taints kernel.”

4)、編譯

輸入“cd /home/zgq/linux/Linux_Drivers/01_MyCharDevice/

輸入“ls

輸入“sudo cp? MyCharDevice.ko? /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31

輸入密碼“123456回車

輸入“cd /home/zgq/linux/nfs/rootfs/lib/modules/5.4.31

輸入“ls

5)、測試

啟動開發板,從網絡下載程序

輸入“root

輸入“cd /lib/modules/5.4.31/

在nfs掛載中,切換到“/lib/modules/5.4.31/”目錄,

注意:“lib/modules/5.4.31/在虛擬機中是位于“/home/zgq/linux/nfs/rootfs/”目錄下,但在開發板中,卻是位于根目錄中

輸入“ls

輸入“depmod”,驅動在第一次執行時,需要運行“depmod”

輸入“modprobe MyCharDevice.ko”,加載“MyCharDevice.ko”模塊

輸入“lsmod”查看有哪些驅動在工作

輸入“rmmod MyCharDevice.ko”,卸載“MyCharDevice.ko”模塊

注意:輸入“rmmod MyCharDevice”也可以卸載“MyCharDevice.ko”模塊

輸入“lsmod”查看有哪些驅動在工作

輸入“modprobe MyCharDevice.ko”,加載“MyCharDevice.ko”模塊

輸入“cat /proc/devices回車”查詢設備號

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/713730.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713730.shtml
英文地址,請注明出處:http://en.pswp.cn/news/713730.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【六袆 - React】Next.js:React 開發框架;Next.js開發框架的特點

Next.js&#xff1a;React 開發框架 Next.js的特點 1.直觀的、基于頁面的路由系統&#xff08;并支持動態路由&#xff09; Next.js 提供了基于文件系統的路由&#xff0c;意味著你可以通過創建頁面文件來定義路由。 偽代碼示例&#xff1a; // pages/index.js export defa…

【GStreamer】basic-tutorial-2:創建、鏈接GstElement,修改其屬性、狀態

【目錄】郭老二博文之:圖像視頻匯總 1、示例注釋 #include <gst/gst.h>int main (int argc, char *argv[]) {GstElement *pipeline,

MYSQL--JDBC優化

一.JDBC優化: 優化前提: 有時候我們并不清楚某些表當中一共有多少列,以及這些列的數據類型,這個時候我們就需要提前通過一些方法提前了解到這些數據,從而更好的進行輸出 具體語句: package cn.jdbc;import java.sql.*;public class JDBCDEmo1 {public static void main(String…

C語言中的動態內存管理技巧:實現靈活的內存分配和釋放

概念 在C語言中&#xff0c;動態內存管理是實現靈活內存分配和釋放的關鍵。合理地管理動態內存可以提高程序的效率和擴展性。本文將介紹C語言中常用的動態內存管理方法和技巧&#xff0c;幫助讀者優化內存分配和釋放的過程。 常用的動態內存管理方法 內存分配&#xff1a;C語…

【數學建模獲獎經驗】2023第八屆數維杯數學建模:華中科技大學本科組創新獎獲獎分享

2024年第九屆數維杯大學生數學建模挑戰賽將于&#xff1a;2024年5月10日08:00-5月13日09:00舉行&#xff0c;近期同學們都開始陸續進入了備賽階段&#xff0c;今天我們就一起來看看上一屆優秀的創新獎選手都有什么獲獎感言吧~希望能幫到更多熱愛數學建模的同學。據說點贊的大佬…

elment-ui table表格排序后 清除排序箭頭/恢復默認排序 的高亮樣式

問題描述&#xff1a; 1.默認排序是按照名稱升序排列&#xff08;圖一&#xff09; 2.在選擇了篩選項以及其他排序方式之后&#xff0c;箭頭高亮是這樣的&#xff08;圖二&#xff09; 3.當我點擊清空按鈕后&#xff0c;類型清空了&#xff0c;并且傳給后端的排序方式是名稱/升…

探索色彩搭配的奧秘:如何選擇適合產品的理想配色方案

title: 探索色彩搭配的奧秘&#xff1a;如何選擇適合產品的理想配色方案 date: 2024/3/1 20:47:45 updated: 2024/3/1 20:47:45 tags: 色彩搭配品牌形象用戶體驗情感連接信息傳達視覺層次色調選擇 引言 友善的色彩搭配和色調選擇是現代產品設計中不可忽視的關鍵因素。通過正確…

Linux yum安裝pgsql出現Bad GPG signature錯誤

官方文檔&#xff1a;https://www.postgresql.org/download/linux/redhat/ sudo yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm sudo yum install -y postgresql12-server sudo /usr/pgsql-12/bin/…

Rust使用calamine讀取excel文件,Rust使用rust_xlsxwriter寫入excel文件

Rust使用calamine讀取已存在的test.xlsx文件全部數據&#xff0c;還讀取指定單元格數據&#xff1b;Rust使用rust_xlsxwriter創建新的output.xlsx文件&#xff0c;并寫入數據到指定單元格&#xff0c;然后再保存工作簿。 Cargo.toml main.rs /*rust讀取excel文件*/ use cala…

Pytest-parametrize實現測試用例與測試數據分離

Pytest自動化框架&#xff0c;實現自動化測試用例與測試數據分離方法&#xff1a; 1.測試用例數據準備&#xff0c;使用yaml文件編輯&#xff0c;如下述teladress.yaml 2.通過pytest框架裝飾器pytest.mark.parametrize實現測試數據傳參 示例&#xff1a; 測試用例文件&…

Tomcat 架構

一、Http工作原理 HTTP協議是瀏覽器與服務器之間的數據傳送協議。作為應用層協議&#xff0c;HTTP是基于TCP/IP協議來傳遞數據的&#xff08;HTML文件、圖片、查詢結果等&#xff09;&#xff0c;HTTP協議不涉及數據包&#xff08;Packet&#xff09;傳輸&#xff0c;主要規定了…

c語言之字符串的輸入和輸出

c語言在輸出字符串時&#xff0c;用格式符‘%s"&#xff0c;代碼比較簡潔 如果說數組長度大于字符串長度&#xff0c;也只輸出\0前的內容 字符串默認后面有\0. 如果字符串有多個\0&#xff0c;會默認在第一個\0結束 #include<stdio.h> int main() {int i;char a…

GO數組切片

1. 數組 數組是一個由固定長度的特定類型元素組成的序列&#xff0c;一個數組可以由零個或多個元素組成。 因為數組的長度是固定的&#xff0c;所以在Go語言中很少直接使用數組。 Go語言數組的聲明&#xff1a; var 數組變量名 [元素數量]Type 1 數組變量名&#xff1a;數…

本地快速部署谷歌開放模型Gemma教程(基于WasmEdge)

本地快速部署谷歌開放模型Gemma教程&#xff08;基于WasmEdge&#xff09; 一、介紹 Gemma二、部署 Gemma2.1 部署工具2.1 部署步驟 三、構建超輕量級 AI 代理四、總結 一、介紹 Gemma Gemma是一系列輕量級、最先進的開放式模型&#xff0c;采用與創建Gemini模型相同的研究和技…

持續集成(CICD)- Jenkins插件安裝失敗解決辦法

解決辦法&#xff1a;將插件安裝更新源需要改成國內鏡像源 具體步驟如下&#xff1a; 步驟一&#xff1a;修改Jenkins工作目錄下的 hudson.model.UpdateCenter.xml 文件&#xff0c;將url 改為http://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json 步驟二…

RuoYi-Vue-Plus功能分析-jackson配置

文章目錄 前言一、配置文件二、配置類三、注解四、json工具類1. 工具內容2. 使用工具 前言 前端在給我發送請求的時候一般包含三個部分url&#xff0c;header&#xff0c;body。那么就會涉及我們后端如何接收這些請求參數并且我們處理完畢參數后前端又如何接收參數 通過url傳…

代碼隨想錄刷題筆記 DAY 37 | 動態規劃理論基礎 | 斐波那契數 No.509 | 爬樓梯 No.70 | 使用最小花費爬樓梯 No.746

文章目錄 Day 3700. 動態規劃理論基礎01. 斐波那契數&#xff08;No. 509&#xff09;<1> 題目<2> 筆記<3> 代碼 02. 爬樓梯&#xff08;No. 70&#xff09;<1> 題目<2> 筆記<3> 代碼 03. 使用最小花費爬樓梯&#xff08;No. 746&#xff…

ECMAScript-262 @2023版本中的關鍵字和保留字

1、什么是標識符&#xff1f; 所謂標識符&#xff0c;就是javascript里的變量、函數、屬性或函數參數的名稱&#xff0c;可由一個或多個字符組成&#xff0c;當然標識符有命名規范 標識符第一個字符必須是 一個字母、下劃線&#xff08;_&#xff09;或美元符號&#xff08;$…

ONLYOFFICE文檔8.0全新發布:私有部署、卓越安全的協同辦公解決方案

ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案 文章目錄 ONLYOFFICE文檔8.0全新發布&#xff1a;私有部署、卓越安全的協同辦公解決方案摘要&#x1f4d1;引言 &#x1f31f;正文&#x1f4da;一、ONLYOFFICE文檔概述 &#x1f4ca;二、ONLYOFFI…

【新書推薦】10.2 分支程序設計

稍微復雜一些的程序通常需要做某種條件判斷&#xff0c;然后再決定程序的執行流程。當然也可以無條件跳轉到程序的另一處地址開始執行。本節我們將詳細介紹分支結構的程序設計方法。 針對功能較為復雜的程序&#xff0c;程序開發有一套標準的流程&#xff0c;我們將10.1節中的五…