樹莓派IO口驅動代碼的編寫、微機總線地址、物理地址、虛擬地址、BCM2835芯片手冊

地址總線:

  • 百度百科解釋: 地址總線 (Address Bus;又稱:位址總線) 屬于一種電腦總線 (一部份),是由CPU 或有DMA
    能力的單元,用來溝通這些單元想要存取(讀取/寫入)電腦內存元件/地方的實體位址。

  • CPU尋找外部的內存單元靠的是地址總線傳輸的數據。 如果CPU有8根地址總線,每根線上傳輸0或1,那么傳輸的數據范圍為00000000~ 11111111,每一個數值都對應內存中的一個內存單元,所以可以找到編號為00000000~ 11111111號的內存單元。如果傳輸的數據為 00110011,那么就會找到00110011號內存單元,如果傳輸的數據為10110111,那么就會找到10110111號內存單元。編號不在[00000000,11111111]范圍內的CPU就尋找不到,例如100000000號內存單元,CPU就尋找不到。尋址能力就是計算CPU能尋找多少個內存單元,00000000~11111111號內存單元,一共有256個,一個內存單元的大小為1byte,這256個內存單元的大小為256byte。

  • CPU是通過地址總線來指定存儲單元的。

  • 地址總線決定了cpu所能訪問的最大內存空間的大小。eg: 10根地址線能訪問的最大的內存為1024(2的10次方)位二進制數據(1B)

  • 地址總線是地址線數量之和。若CPU的地址總線寬度是32位,那么CPU的尋址范圍是4G(2的32次方位),所以最多支持4G內存。

  • 比如有一個現象:裝了32位的win7系統,明明內存條8G,可系統只是別了3.8G ,裝了64位才能識別到8G。裝了32位的操作系統CPU的訪問范圍是2^32 bit,就是4194304kbit,就是4096Mbit,等于4G。樹莓派也是32位 ,一個G的內存,但它只能訪問949M剩下的挪作他用。

數據總線:

  • CPU通過地址總線尋址,然后通過數據總線與外部設備互換信息。
  • 是CPU與內存或其他器件之間的數據傳送的通道。
  • 數據總線的寬度決定了CPU和外界的數據傳送速度。
  • 每條傳輸線一次只能傳輸1位二進制數據。eg: 8根數據線一次可傳送一個8位二進制數據(即一個字節)。
  • 數據總線是數據線數量之和,數據總線的位數決定CPU單次通信能交換的信息數量。

數據總線的寬度對CPU的性能的影響:

  • 首先,總線的速度(即:CPU的主頻,CPU的性能指標之一)決定CPU和外設互換信息的速度。
  • 其次,數據總線的寬度也是表示CPU性能的參數之一(通常,我們說“64位的CPU”是指CPU的數據總線的寬度是64位)。 如:64位數據總線的CPU一次就能取出64bit的數據,8位數據總線的CPU一次只能取出8bit的數據,在相同頻率的情況下,8位數據總線的CPU就得連續取8次數據,數據量才能和64位數據總線一次取出的數據量相同,單就比較取數據的性能就相差8倍。況且,通常CPU中的寄存器的位數與數據總線的寬度一樣,所以在數據處理方面,64位的CPU又比8位的CPU快很多。
  • CPU的地址總線位數和數據總線可以不同(典型代表就是51單片機),但是一般都相同。16位機有16根數據總線,20根地址總線,能訪問1M(2的20次方),32位機有32根數據總線,32根地址總線,能訪問4G(2的32次方),64位機確實有64根數據總線。

物理地址(PA):

  • 百度百科解釋: 網卡物理地址存儲器中存儲單元對應實際地址稱物理地址,與邏輯地址相對應。網卡的物理地址通常是由網卡生產廠家寫入網卡的EPROM(一種閃存芯片,通常可以通過程序擦寫),它存儲的是傳輸數據時真正賴以標識發出數據的電腦和接收數據的主機的地址。
  • 這里說的物理地址是內存中的內存單元實際地址,不是外部總線連接的其他電子元件的地址!物理地址屬于比較好理解的,物理地址就是內存中每個內存單元的編號,這個編號是順序排好的,物理地址的大小決定了內存中有多少個內存單元,物理地址的大小由地址總線的位寬決定!

虛擬地址(VA):

  • 虛擬地址是Windows程序時運行在386保護模式下,這樣程序訪問存儲器所使用的邏輯地址稱為虛擬地址,與實地址模式下的分段地址類似,虛擬地址也可以寫為“段:偏移量”的形式,這里的段是指段選擇器。而linux沒有各種保護模式,本來用的就是虛擬地址。
  • 虛擬地址是CPU保護模式下的一個概念,保護模式是80286系列和之后的x86兼容CPU操作模式,在CPU引導完操作系統內核后,操作系統內核會進入一種CPU保護模式,也叫虛擬內存管理,在這之后的程序在運行時都處于虛擬內存當中,虛擬內存里的所有地址都是不直接的,所以你有時候可以看到一個虛擬地址對應不同的物理地址,比如A進程里的call函數入口虛擬地址是0x001,而B也是,但是它倆對應的物理地址卻是不同的,操作系統采用這種內存管理方法。
  • 是防止程序對物理地址寫數據造成一些不可必要的問題,比如知道了A進程的物理地址,那么向這個地址寫入數據就會造成A進程出現問題,在虛擬內存中運行程序永遠不知道自己處于內存中那一段的物理地址上!現在操作系統運行在保護模式下即便知道其他進程的物理地址也不允許向其寫入!但是可以通過操作系統留下的后門函數獲取該進程上的虛擬地址空間所有控制權限并寫入指定數據。
  • 虛擬內存管理采用一種拆東墻補西墻的形式,所以虛擬內存的內存會比物理內存要大許多。在進入虛擬模式之前CPU以及Bootloader(BootLoader是在操作系統內核運行之前運行。可以初始化硬件設備、建立內存空間映射圖,從而將系統的軟硬件環境帶到一個合適狀態,以便為最終調用操作系統內核準備好正確的環境),操作系統內核均運行在實模式下,直接對物理地址進行操作!虛擬內存中也有分頁管理,這種管理方法是為了確保內存中不會出現內存碎片,當操作系統內核初始化完畢內存中的分頁表后CPU的分頁標志位會被設置,這個分頁標志位是給MMU看的!
  • MMU是Memory Management Unit的縮寫,中文名是內存管理單元,它是中央處理器(CPU)中用來管理虛擬存儲器、物理存儲器的控制線路,同時也負責虛擬地址映射為物理地址,以及提供硬件機制的內存訪問授權,多用戶多進程操作系統。作用有兩點,地址翻譯和內存保護。MMU將虛擬地址翻譯為物理地址。

分頁管理:

  • 內存分頁其實就是我們所說的4G空間,內存的所有內存被操作系統內核以4G為每頁劃分開,當我們程序運行時會被加載到內存中的4G空間里,其實說是有4G其實并沒有真正在的4G空間,4G空間中有一小部分被映射到了物理內存中,或者被映射到了硬盤的文件上(fopen),或者沒有被映射,還有一部分在內存當中就會被劃分棧,堆,其中有大片大片的內存是沒有被映射的,同樣物理內存也是被分頁了用來與虛擬內存產生映射關系。將虛擬地址映射為物理地址有一個算法(頁表)決定了將虛擬地址映射到物理地址的哪個位置,頁表是通過MMU(分頁內存管理單元)來管理的,就是設計完頁表后通過MMU來執行將虛擬地址映射為物理地址。
  • 其實真正情況下只有3G用戶空間,假如你的內存是4G的那么其中有1G是給操作系統內核使用的,所謂的4G空間只是操作系統基于虛擬內存這種拆東墻補西墻的形式給你一種感覺每個進程都有4G的可用空間一樣!這里來說一下拆東墻補西墻,當我們程序被加載進4G空間時其實根本用不了所謂的4G空間,其中有大片內存被閑置,那么這個時候呢,其他程序被加載進來時發現內存不夠了,就把其他程序里的4G空間里閑置部分拿出來給這個進程用,換之這個進程內存不夠時就會把其他進程里閑置的空間拿過來給該進程使用。銀行也是如此!
  • 當我們要對物理地址做操作時比如if語句要根據CPU的狀態標志寄存器來做不同的跳轉,那么這個時候就要對CPU額狀態寄存器做操作了就必須知道它的物理地址,內存中有一個電子元件叫MMU負責從操作系統已經初始化好的內存映射表里查詢與虛擬地址對應的物理地址并轉換,比如mov
    0x4h8這個是虛擬地址,當我們要對這個虛擬地址里寫數據時那么MMU會先判斷CPU的分頁狀態寄存器里的標志狀態是否被設定,如果被設定那么MMU就會捕獲這個虛擬地址物理并在操作系統內核初始化好的內存映射表里查詢與之對應的物理地址,并將其轉換成真正的實際物理地址,然后在對這個實際的物理地址給CPU,在由CPU去執行對應的命令,相反CPU往內存里讀數據時比如A進程要讀取內存中某個虛擬地址的數據,A進程里的指令給的是虛擬地址,MMU首先會檢查CPU的分頁狀態寄存器標志位是否被設置,如果被設置MMU會捕獲這個虛擬地址并將其轉換成相應的物理地址然后提交給CPU,在由CPU到內存中去取數據!

下面截取樹莓派芯片手冊的一張圖:
在這里插入圖片描述
BCM2835是樹莓派3B CPU的型號,是ARM-cotexA53架構,cpu Bus是地址總線,00000000~FFFFFFFF是CPU尋址的范圍。DMA是高速拷貝單元,CPU可以發動DMA直接讓DMA進行數據拷貝,直接內存訪問單元。

  • 通過芯片手冊了解樹莓派的GPIO:有54條通用I/O GPIO行,分為兩行,備用功能通常是外圍IO并且可以在每個銀行中出現一個外圍設備,以允許靈活地選擇IO電壓。
    在這里插入圖片描述
  • GPIO有41個寄存器,所有訪問都是32位的。Description是寄存器的功能描述。GPFSEL0(寄存器名) GPIO Function Select 0(功能選擇:輸入或輸出);GPSET0 (寄存器名) GPIO Pin Output Set 0(將IO口置0);GPSET1(寄存器名) GPIO Pin Output Set 1(將IO口置1);GPCLR0(寄存器名) GPIO Pin Output Clear 0 (清0)下圖的地址是:總線地址(并不是真正的物理地址)
    在這里插入圖片描述
  • FSELn表示GPIOn,下圖給出第九個引腳的功能選擇示例,對寄存器的29-27進行配置,進而設置相應的功能。根據圖片下方的register 0表示0~9使用的是register 0這個寄存器。
    在這里插入圖片描述
    在這里插入圖片描述
  • 輸出集寄存器用于設置GPIO管腳。SET{n}字段定義,分別對GPIO引腳進行設置,將“0”寫入字段沒有作用。如果GPIO管腳為在輸入(默認情況下)中使用,那么SET{n}字段中的值將被忽略。然而,如果引腳隨后被定義為輸出,那么位將被設置根據上次的設置/清除操作。分離集和明確功能取消對讀-修改-寫操作的需要。GPSETn寄存器為了使IO口設置為1,set4位設置第四個引腳,也就是寄存器的第四位。
    在這里插入圖片描述
  • 輸出清除寄存器用于清除GPIO管腳。CLR{n}字段定義要清除各自的GPIO引腳,向字段寫入“0”沒有作用。如果的在輸入(默認),然后在CLR{n}字段的值是忽略了。然而,如果引腳隨后被定義為輸出,那么位將被定義為輸出根據上次的設置/清除操作進行設置。分隔集與清函數消除了讀-修改-寫操作的需要。GPCLRn是清零功能寄存器。
    在這里插入圖片描述
  • 配置樹莓派的pin4引腳為輸出引腳: 只需要將GPFSL0這個寄存器的14~12位設置為001就可以了。只需要將0x6(對應的2進制是110)左移12位·然后取反再與上GPFSL0就可以將13、14這兩位配置為0,然后再將0x6(對應2進制110)左移12位,然后或上GPFSL0即可將12位置1。
  • 可使用copy_from_user()這個函數在驅動代碼里面讀取用戶輸入的指令,使用copy_to_user()這個函數讓引腳反饋現在的狀態,也就是讓用戶讀取到。

ioremap、iounmap:

一、 一般我們的外設都是通過讀寫設備上的寄存器來進行的,通常包括控制寄存器、狀態寄存器、數據寄存器三大類。外設的寄存器通常被連續編址,并且根據CPU的體系架構不同CPU對IO端口的編制方式有兩種:

  • IO映射方式(IO-mapped):比較典型的有X86處理器為外設專門實現了一個單獨的地址空間,稱為“IO端口空間”或者“IO地址空間”,此時CPU可以通過專門的指令(比如X86的IN和OUT)來訪問這個“IO端口空間”。
  • 內存映射方式(memory-mapped):RISC指令系統的CPU一般只實現一個物理地址空間,外設IO端口成為內存的一部分。此時CPU可以訪問外設的IO端口,就像訪問自己的內存一樣方便,不必再設置專門的指令來訪問。在驅動開發過程中一般使用內存映射方式。

二、 在驅動開發過程中,一般來說外設的IO內存資源的物理地址是已知的,由硬件的設計決定。但是CPU不會為這些已知的外設IO內存資源預先指定虛擬地址的值,所以驅動程序不可以直接就通過外設的物理地址訪問到IO內存,而必須要將其映射到虛擬地址空間(通過頁表),然后才能根據內核映射過后的虛擬地址來通過內存指令訪問這些IO內存,并對其進行操作。

三、 在Linux內核的io.h頭文件中聲明了ioremap()函數,用來將IO內存資源映射到核心虛擬地址空間(3Gb~4GB)中,當然不用了可以將其取消映射iounmap()。這兩個函數在mm/ioremap.c文件中:

開始映射:void* ioremap(unsigned long phys_addr , unsigned long size , unsigned long flags)
//用map映射一個設備意味著使用戶空間的一段地址關聯到設備內存上,這使得只要程序在分配的地址范圍內進行讀取或寫入,實際上就是對設備的訪問。
第一個參數是映射的起始地址
第二個參數是映射的長度
第二個參數怎么定啊?
====================
這個由你的硬件特性決定。
比如,你只是映射一個32位寄存器,那么長度為4就足夠了。
(這里樹莓派IO口功能設置寄存器、IO口設置寄存器都是32位寄存器,所以分配四個字節就夠了)比如:GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4);GPSET0 =(volatile unsigned int *)ioremap(0x3f20001C,4);GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);
這三行是設置寄存器的地址,volatile的作用是作為指令關鍵字
確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值
ioremap函數將物理地址轉換為虛擬地址,IO口寄存器映射成普通內存單元進行訪問。解除映射:void iounmap(void* addr)//取消ioremap所映射的IO地址
比如:iounmap(GPFSEL0);iounmap(GPSET0);iounmap(GPCLR0); //卸載驅動時釋放地址映射

樹莓派IO口四的驅動代碼:

#include <linux/fs.h>            //file_operations聲明
#include <linux/module.h>    //module_init  module_exit聲明
#include <linux/init.h>      //__init  __exit 宏定義聲明
#include <linux/device.h>        //class  devise聲明
#include <linux/uaccess.h>   //copy_from_user 的頭文件
#include <linux/types.h>     //設備號  dev_t 類型聲明
#include <asm/io.h>          //ioremap iounmap的頭文件static struct class *pin4_class;
static struct device *pin4_class_dev;static dev_t devno;                //設備號
static int major =231;                     //主設備號
static int minor =0;                       //次設備號
static char *module_name="pin4";   //模塊名volatile unsigned int* GPFSEL0 = NULL;
volatile unsigned int* GPSET0   = NULL;
volatile unsigned int* GPCLR0   = NULL;
//這三行是設置寄存器的地址,volatile的作用是作為指令關鍵字,確保本條指令不會因編譯器的優化而省略,且要求每次直接讀值//led_open函數
static int pin4_open(struct inode *inode,struct file *file)
{printk("pin4_open\n");  //內核的打印函數和printf類似*GPFSEL0 &=~(0x6 <<12); // 把13 、14置為0*GPFSEL0 |=~(0x6 <<12); //把12置為1return 0;}
//read函數
static int pin4_read(struct file *file,char __user *buf,size_t count,loff_t *ppos)
{printk("pin4_read\n");  //內核的打印函數和printf類似return 0;
}//led_write函數
static ssize_t pin4_write(struct file *file,const char __user *buf,size_t count, loff_t *ppos)
{int usercmd;printk("pin4_write\n");  //內核的打印函數和printf類似copy_from_user(&usercmd,buf,count); //將應用層用戶輸入的指令讀如usercmd里面if(usercmd == 1){printk("set 1\n");*GPSET0 |= 0x01 << 4;}else if(usercmd == 0){printk("set 0\n");*GPCLR0 |= 0x01 << 4;}else{printk("undo\n");}return 0;
}static struct file_operations pin4_fops = {.owner = THIS_MODULE,.open  = pin4_open,.write = pin4_write,.read  = pin4_read,
};//static限定這個結構體的作用,僅僅只在這個文件。
int __init pin4_drv_init(void)   //真實的驅動入口
{int ret;devno = MKDEV(major,minor);  //創建設備號ret   = register_chrdev(major, module_name,&pin4_fops);  //注冊驅動  告訴內核,把這個驅動加入到內核驅動的鏈表中pin4_class=class_create(THIS_MODULE,"myfirstdemo");//讓代碼在dev下自動>生成設備pin4_class_dev =device_create(pin4_class,NULL,devno,NULL,module_name);  //創建設備文件GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4);GPSET0 =(volatile unsigned int *)ioremap(0x3f20001C,4);GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);printk("insmod driver pin4 success\n");return 0;
}void __exit pin4_drv_exit(void)
{iounmap(GPFSEL0);iounmap(GPSET0);iounmap(GPCLR0); //卸載驅動時釋放地址映射device_destroy(pin4_class,devno);class_destroy(pin4_class);unregister_chrdev(major, module_name);  //卸載驅動
}
module_init(pin4_drv_init);  //入口,內核加載驅動的時候,這個宏會被調用,去調用pin4_drv_init這個函數
module_exit(pin4_drv_exit);
MODULE_LICENSE("GPL v2");

上層測試代碼:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{int fd,data;fd = open("/dev/pin4",O_RDWR);printf("plese input 1 or 0 //1:high 0:low\n ");scanf("%d",&data);if(fd<0){printf("open fail\n");perror("reson:");}else{printf("open successful\n");}fd=write(fd,&data,1);
}
  • 首先使用指令:ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make modules對驅動模塊進行編譯生成.ko文件,然后將編譯后的驅動發送到樹莓派:scp pin4drive.ko pi@192.168.43.136:/home/pi,然后再將上層代碼進行編譯:arm-linux-gnueabihf-gcc pin4test.c -o pin4test,然后再將測試代碼傳到樹莓派:scp pin4test pi@192.168.43.136:/home/pi/
  • 然后在樹莓派上面使用指令:insmod pin4drive.ko進行加載驅動(然后lsmod即可查看到該驅動),然后使用指令:sudo chmod 666 /dev/pin4給予pin4這個設備可訪問權限,還可以在虛擬機上面使用mk5sum查看驅動文件的值,并在樹莓派上面使用該指令進行查看該驅動文件的值,看是否一致。dmesg查看內核打印的信息,如下圖所示:
    在這里插入圖片描述
  • 然后運行測試代碼,在新建一個窗口,使用指令gpio readall可以看到BCM下面的4號引腳模式是輸出模式,電平是低電平或高電平(根據輸入的上層代碼而定,輸入0就是低電平,輸入1就是高電平),這里我輸入的是0,如下圖所示:
    在這里插入圖片描述
  • 然后的dmesg查看內核打印的消息,如下圖所示:
    在這里插入圖片描述

有關驅動代碼里面GPIO口地址的問題:
在這里插入圖片描述在這里插入圖片描述

  • 7Ennnnn意思是7E00000到7EFFFFFF,F2000000是3F000000映射的虛擬地址,然后7E00000和F200000對應,芯片手冊里面使用的是和虛擬地址F200000有著對應關系的地址——7E00000,芯片手冊上面地址偏移多少物理地址就偏移多少
  • 根據上方圖片描述,外設的物理地址范圍是m 0x3F000000 to 0x3FFFFFFF,所以你看到的7E200000對應的實際物理地址應該是0x3F000000 + (7E200000-7E000000)
  • GPFSEL0=(volatile unsigned int *)ioremap(0x3f200000,4);
    GPSET0 =(volatile unsigned int *)ioremap(0x3f20001C,4);
    GPCLR0 =(volatile unsigned int *)ioremap(0x3f200028,4);
  • 0x3f200000,0x3f20001C,0x3f200028是物理地址,樹莓派的外設空間的起始地址是0x3f000000,根據芯片手冊可知對應寄存器的偏移量為,比如GPFSEL0寄存器的實際地址是0x3f200000=0x3F000000 + (7E200000-7E000000)
  • 然后通過數據手冊可以看到,樹莓派相關寄存器的總線地址(和映射的虛擬地址有某種對應關系的地址)進而可得知偏移量,如下圖所示:
    在這里插入圖片描述

有關各種地址介紹的博文:

  • 物理地址、虛擬地址、總線地址
  • 物理地址和總線地址區別

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

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

相關文章

奪命雷公狗---DEDECMS----26dedecms面包屑導航的實現

我們在很多項目里面都會用到面包屑導航&#xff0c;而dedecms里面也是給我們封裝好面包屑導航的了,如下圖所示&#xff1a; 在dede里面實現面包屑導航主要用到{dede:field.position/}標簽&#xff0c;我們首先來修改下article_movie.htm內容頁的模版文件&#xff1a; 我們修改成…

rust油桶用什么打_草莓用什么膨大素好?草莓膨大劑什么時間打?草莓用什么肥料膨大...

農資365公眾號&#xff0c;了解更多生根、根腐、重茬、土傳、枯黃萎、根爛病、防治根結線蟲、微生物菌肥、膨大坐果、抗病增產的防治方法&#xff01;草莓含有豐富的營養&#xff0c;并且種植效益較高&#xff0c;其種植范圍也比較廣。草莓種植期間有很多因素影響草莓果實膨大&…

docker安裝kafka,超級簡單的

簡介 kafka是一個分布式消息隊列。具有高性能、持久化、多副本備份、橫向擴展能力。生產者往隊列里寫消息&#xff0c;消費者從隊列里取消息進行業務邏輯。一般在架構設計中起到解耦、削峰、異步處理的作用。 kafka對外使用topic的概念&#xff0c;生產者往topic里寫消息&…

Linux中常見的環境變量筆記

1、變量&#xff1a;BASHBash Shell的全路徑比如&#xff1a;echo $BASH2、變量&#xff1a;BASH_VERSIONBash Shell的版本號3、變量&#xff1a;EUID記錄當前用戶的UID。root用戶值為0。4、FUNCNAME在用戶函數體內部&#xff0c;記錄當前函數體的函數名。5、變量&#xff1a;H…

消防信號二總線有沒電壓_春曉161#地塊人防工程消防電源監控系統的設計與應用...

涂志燕安科瑞電氣股份有限公司&#xff0c;上海 嘉定 201801&#xff1b;摘要&#xff1a;本文簡述了消防設備電源的組成原理&#xff0c;分析了消防設備電源監控系統在應用中的設計依據和相關規范。通過安科瑞消防設備電源監控系統在春曉161#地塊項目的實例介紹&#xff0c;闡…

大學慕課數據結構單元測試——華中科技大學

第一章緒論單元測試 一、單選(2分) 1、?___C__ 是數據的最小單位。 A.信息項 B.數據元素 C.數據項 D.表元素 2、?以下說法不正確的是 ___B___。 A.數據元素是數據的基本單位 B.數據項可由若干個數據元素構成 C.數據可由若干個數據元素構成 D.數據項是不可分割的最小…

gitlab應用

1.git config --global user.email "mybimt.com"  //注冊本地環境 2.ssh-keygen -t rsa -C "mybimt.com" //生成本機的key 3.在gitlab加入.ssh中生成的key //gitlab中注冊本機 4.git clone gitmy.git …

RocketMQ同步刷盤和異步刷盤

刷盤機制 同步刷盤和異步刷盤 在broker配置文件里修改參數配置是同步還是異步

vim模式下報錯E37: No write since last change No write since last change for buffer “ “

報錯如下圖所示&#xff1a; 網上的解決方法&#xff1a; 文件為只讀文件&#xff0c;無法修改。使用命令:w!強制存盤即可在vim模式下&#xff0c;鍵入以下命令&#xff1a;:w&#xff01;存盤后在使用vim命令檢查是否保存&#xff0c;如未保存&#xff0c;編輯后重復以上操作…

Linux中Shell中取消變量和特殊變量的筆記

1、取消變量取消變量也就是將變量從內存中釋放出去&#xff0c;可以使用unset 后面加變量名即可&#xff0c;當然函數的釋放同樣可以采用該方式處理。比如&#xff1a;name"123"echo ${name}輸出&#xff1a;123unset nameecho ${name}輸出&#xff1a;#取消函數示例…

光華科技光刻膠_【收藏】6天5板!21只光刻膠概念(名單)“出爐”!

連板數量21家中迪投資5板&#xff0c;寧波聯合 神馳機電 神馬電力4板&#xff0c;漢纜股份 華盛昌 浙江鼎力3板&#xff0c;海航投資世聯行 飛龍股份 安潔科技 京威股份 三豐智能 容大感光 晶瑞股份 奧飛數據 光大嘉寶 電子城博天環境 兆易創新 聚辰股份2板二、科技股&#xff…

20159302 《網絡攻擊與防范》第四周學習總結

本節學習內容為網絡攻擊環境的配置。在此過程中&#xff0c;我們至少需要一臺靶機&#xff0c;一臺攻擊機。在此選用windows server 2000為靶機&#xff0c;kali系統為攻擊機。 一、系統的安裝 根據之前發布的kali系統的安裝過程&#xff0c;依據此流程進行windows server的安裝…

智能家居項目開發準備工作

智能家居功能細節拆分&#xff1a; 控制端支持語音設備的輸入&#xff08;用到之前所學習的LD3320語音識別模塊&#xff09;或者是socket客戶端&#xff08;這個客戶端可以是ftp項目的客戶端也可以是Android的app&#xff09;&#xff0c;主控芯片是樹莓派&#xff0c;既接收語…

catia曲面掃掠命令詳解_Mastercam快捷鍵命令,附中英文功能講解!值得收藏!

組合鍵式快捷鍵功能快 捷 鍵功能Alt 0設置Z向控制深度Alt 1設置繪制圖形的顏色Alt 2設置當前層Alt 3與Alt 2功能相同Alt 4設置刀具面(Tplane)Alt 5設置繪圖面(Cplane)Alt 6設置視圖面(Gview)Alt A進入自動存文件對話框快 捷 鍵功能Alt B工具條的顯示/關閉Alt C選擇執…

RocketMQ中主從復制

生產者把消息發送到master&#xff0c;不會發送到slave 消費者可以從maste也可以從slave消費消息 如果master掛了&#xff0c;那就從slave消費數據&#xff0c;那么slave怎么拿到master中的數據 這就要用到主從復制

智能家居代碼構建編寫、簡單工廠模式、樹莓派攝像頭視頻監控功能實現

根據上一節內容的代碼框架開始編寫代碼&#xff1a; 首先編寫controlDevices.h這個頭文件里面的代碼&#xff0c;這個是設備工廠每一個結點的結構體類型&#xff0c;而且還要在這個頭文件里面進行函數的聲明&#xff0c;也就是創建的那些設備.c文件里面的函數&#xff08;為了…

Linux中Shell的命令替換用法筆記

命令替換主要是指將命令的標準輸出值賦值給某個變量。命令替換屬于Shell編程中非常重要的功能&#xff0c;需要熟悉掌握。 命令替換的方式 1、反引號:命令 2、$()&#xff1a;$(命令) 用法說明&#xff1a;date1date #將date命令值給date1變量 date2$(date) #將date命令值給dat…

采樣次數不同平均值不一樣_網絡推廣采取的方式不同,效果也不一樣

網絡推廣是基于互聯網而進行&#xff0c;針對目標客戶群體&#xff0c;加之以有效的網絡鏈接形式使其形成迅速大的購買力的一種營銷模式&#xff0c;是目前很多企業已經認識到的&#xff0c;但是在推廣過程之中往往會出現不同的狀況&#xff0c;比如說模式是完全不一樣的。 …

rocketmq 同步刷盤和異步刷盤以及主從復制之同步復制和異步復制你理解了嗎

同步刷盤、異步刷盤 RocketMQ的消息是存儲到磁盤上的&#xff0c;這樣既能保證斷電后恢復&#xff0c;又可以讓存儲的消息量超出內存的限制。 RocketMQ為了提高性能&#xff0c;會盡可能地保證磁盤的順序寫。消息在通過Producer寫入RocketMQ的時候&#xff0c;有兩種 寫磁盤方…