Linux驅動開發-①pinctrl 和 gpio 子系統②并發和競爭③內核定時器

Linux驅動開發-①pinctrl 和 gpio 子系統②并發和競爭③內核定時器

  • 一,pinctrl 和 gpio 子系統
    • 1.pinctrl子系統
    • 2.GPIO子系統
  • 二,并發和競爭
    • 1.原子操作
    • 2.自旋鎖
    • 3.信號量
    • 4.互斥體
  • 三,按鍵實驗
  • 四,內核定時器
    • 1.關于定時器的有關概念
      • 1.1 節拍HZ
      • 1.2 jiffies
    • 2.定時器實驗
  • 五,相關問題
    • 1.pin和gpio
    • 2.depmod作用
      • 3.得到gpio后,使用request申請的作用

一,pinctrl 和 gpio 子系統

1.pinctrl子系統

??在linux內核中用于管理和配置引腳復用(比如復用為GPIO,I2C,SPI,UART等)和引腳屬性(電氣屬性:上拉,下拉,驅動強度等)的框架,通過設備樹描述引腳配置。MX6UL_PAD_GPIO1_IO03__GPIO1_IO03宏定義格式 <mux_reg conf_reg input_reg mux_mode input_val>,mux_reg寄存器偏移地址,如果值為0x01,因為 iomux基地址為0x020e0000,因此MUX復用功能寄存器的地址為0x020e0001這樣,同理conf_reg 和input_reg 。mux_mode即mux復用寄存器設置的值。

&iomuxc {pinctrl-names = "default";pinctrl-0 = <&pinctrl_hog_1>;imx6ul-evk {pinctrl_hog_1: hoggrp-1 {fsl,pins = <MX6UL_PAD_UART1_RTS_B__GPIO1_IO19	0x17059 /* SD1 CD */MX6UL_PAD_GPIO1_IO05__USDHC1_VSELECT	0x17059 /* SD1 VSELECT */MX6UL_PAD_GPIO1_IO09__GPIO1_IO09        0x17059 /* SD1 RESET */>;};/*LED*/pinctrl_led: ledgrp{fsl,pins = <MX6UL_PAD_GPIO1_IO03__GPIO1_IO03  0X10B0  /*led設置復用為GOIO1_IO03,電氣屬性設置為0x10B0*/>;};}

2.GPIO子系統

??pinctrl將一個pin復用為GPIO的話,使用GPIO子系統控制,作用是不用操作寄存器就能配置和操作GPIO。首先在設備樹中添加這個led的節點,讓這個節點使用上面配置的屬性并且連接好對應的引腳。在設備樹的根目錄下設置gpled節點,并且用pinctrl-0 = <&pinctrl_led>;使得復用和電器屬性得到設置,led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>讓這個驅動和GPIO1_IO03進行關聯。

/ {gpioled{#adress-cells = <1>;#size-cells = <1>;compatible = "atkalpha-gpioled";princtrl-names = "default";pinctrl-0 = <&pinctrl_led>;led-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;status = "okay";};
};

驅動實現主要利用到設置的這些內容:

static ssize_t pgled_write(struct file *filp, const char __user *buf,size_t cnt,loff_t *offt)
{int ret;unsigned char databuf[1];unsigned char let_status;struct led_dev *pgled_dev = filp->private_data;ret = copy_from_user(databuf,buf,cnt);let_status = databuf[0];if(let_status == 0){gpio_set_value(pgled_dev->led_gpio,0);//開燈}else if(let_status == 1) {gpio_set_value(pgled_dev->led_gpio,1);//關燈}return 0;
}static int __init pgled_init(void)
{int ret =0;led.nd = of_find_node_by_path("/gpioled");//在設備樹中獲取節點led.led_gpio = of_get_named_gpio(led.nd,"beep-gpio", 0);//得到gpio引腳ret = gpio_direction_output(led.led_gpio,1);//設置GPIO1-03為輸出,并且設置為1,高點平關閉if(ret == 0){printk("從設備樹讀取節點和gpio正確\r\n");}/*注冊*//*1.設備號*/if(led.major){led.led_hao = MKDEV(led.major,0);register_chrdev_region(led.led_hao, 1, LED_NAME);//主動注冊}else{alloc_chrdev_region(&led.led_hao, 0, 1, LED_NAME);//自動注冊}printk("major = %d,minor = %d",MAJOR(led.led_hao),MINOR(led.led_hao));/*2.注冊函數*/led.cdev.owner = THIS_MODULE;cdev_init(&led.cdev,&pgled_fops);cdev_add(&led.cdev,led.led_hao,1);/*3.節點申請*/ led.class = class_create(THIS_MODULE,LED_NAME);led.device = device_create(led.class, NULL,led.led_hao, NULL,LED_NAME);/*4.具體實現*/  return 0;
}

二,并發和競爭

??并發:指多個任務(線程、進程或協程)在同一時間段內交替執行的現象。這些任務可能是同時運行的(在多核 CPU 上),也可能是通過時間片輪轉的方式交替運行的(在單核 CPU 上)。
競爭:指多個并發任務在訪問共享資源時,由于執行順序的不確定性,導致程序的最終結果依賴于任務的執行順序。如果未正確同步,可能會導致數據不一致或程序行為異常。下面四種操作就是為了避免訪問共享資源時候出現混亂。
在這里插入圖片描述

1.原子操作

??執行這一步,不被其他線程或者內核影響,相當于我在執行這個操作時候,讓一個標準位置0,其他線程或者內核想執行這個操作,一看這個標志位為0,就執行不了,等到這個操作被我執行完后,把標志位置1,從而其他可以去執行。原子操作即不可分割的操作意思。

2.自旋鎖

??當一個線程或核心嘗試獲取鎖時,如果鎖已被其他線程或核心持有,則該線程或核心會一直“自旋”(即忙等待),直到鎖被釋放。由此可以看出,其他線程或核心在一直自旋,這個時候是浪費cpu的處理能力的,因此自旋鎖適合持鎖時間很短的操作。特點是①不進入休眠,即其它線程或核心要一直等待著,而不是先去執行其他操作,等這個鎖解了再通知回來。②中斷可以用,因為中斷不能休眠。

3.信號量

??信號量就相當于設置一個變量,初始值,我進行這個操作時,這個變量會設置為另一個值,其他線程或者內核看到這個變量不是初始值,不會在外面一直等待,而是去執行其他操作,等我執行完這個操作后,會將這個變量變回初始值,然后通知線程和內核來執行這個操作,適合鎖持有時間較長的情況。

4.互斥體

??互斥體是確保同一時間只有一個線程或進程可以訪問共享資源,從而避免競態條件,當一個線程或進程嘗試獲取互斥體時,如果互斥體已被其他線程或進程持有,則該線程或進程會進入睡眠狀態,直到互斥體被釋放,和信號量基本上一樣,但是互斥體是兩種情況即0 1,信號量是計數器,闊以大于1。

具體使用:

struct led_dev{struct class *class;struct device *device;struct device_node *nd;struct cdev cdev;dev_t led_hao;int major;//主設備號int minor;//次設備號int led_gpio;//led的gpioatomic_t lock_yuan;//原子操作spinlock_t lock_spin;//自旋操作int dev_status;//0可用 1不可用struct semaphore sem;//信號量struct mutex lock_huci;//互斥體};
struct led_dev led;
static int pgled_open(struct inode *innode,struct file *filp)
{/*信號量*/down(&led.sem);/*自旋鎖*/unsigned long flags;spin_lock_irqsave(&led.lock_spin,flags);//上鎖if(led.dev_status){spin_unlock_irqrestore(&led.lock_spin,flags);return -EBUSY;}led.dev_status++;//為0,則讓lock——spin為1標志設備已經被使用了spin_unlock_irqrestore(&led.lock_spin,flags);/*原子操作*/if(atomic_read(&led.lock_yuan)<=0)//被操作了{return -EBUSY;}else {atomic_dec(&led.lock_yuan);}/*互斥體*/if (mutex_lock_interruptible(&led.lock_huci)) {return -ERESTARTSYS;}filp->private_data = &led;//將led結構體數據設為私有數據return 0;
}
static int pgled_release(struct inode *innode,struct file *filp)
{   up(&led.sem);//信號量mutex_unlock(&led.lock_huci);//互斥體unsigned long flags;/*自旋鎖*/spin_lock_irqsave(&led.lock_spin,flags);//上鎖if(led.dev_status){led.dev_status--;}spin_unlock_irqrestore(&led.lock_spin,flags);atomic_inc(&led.lock_yuan);//原子操作return 0;
}static int __init pgled_init(void)
{atomic_set(&led.lock_yuan,1);//原子操作,鎖設置 當為1可以操作,否則不可以操作spin_lock_init(&led.lock_spin);//自旋sema_init(&led.sem,1);//信號量mutex_init(&led.lock_huci);//互斥體
}

三,按鍵實驗

驅動:

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fs.h>  // 包含 register_chrdev_region 的定義
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/semaphore.h>#define KEY_NAME "key"
#define KEY_VALUE  0X01
#define KEY_NOVALUE 0X00struct key_dev{struct class *class;struct device *device;struct device_node *nd;struct cdev cdev;dev_t key_hao;int major;//主設備號int minor;//次設備號int key_gpio;//key的gpioatomic_t key_value;//原子操作// spinlock_t lock_spin;//自旋操作// int dev_status;//0可用 1不可用// struct semaphore sem;//信號量// struct mutex lock_huci;//互斥體};
struct key_dev key;static void  keyio_init(void)
{int ret = 0;key.nd = of_find_node_by_path("/gpiokey");//在設備樹中獲取節點key.key_gpio = of_get_named_gpio(key.nd,"key-gpio", 0);//得到gpio引腳gpio_request(key.key_gpio,"key0");ret = gpio_direction_input(key.key_gpio);//設置為輸入if(ret == 0){printk("從設備樹讀取節點和gpio正確\r\n");}}
static int pgkey_open(struct inode *innode,struct file *filp)
{keyio_init();//初始化IOfilp->private_data = &key;//將key結構體數據設為私有數據return 0;
}
static int pgkey_release(struct inode *innode,struct file *filp)
{   // up(&key.sem);//mutex_unlock(&key.lock_huci);// unsigned long flags;// /*自旋鎖*/// spin_lock_irqsave(&key.lock_spin,flags);//上鎖// if(key.dev_status)// {//      key.dev_status--;// }// spin_unlock_irqrestore(&key.lock_spin,flags);// atomic_inc(&key.lock_yuan);// printk("打開后  關閉:close_file  lock_yuan = %d\r\n",key.lock_yuan);return 0;
}
static ssize_t pgkey_read(struct file *filp, char __user *buf,size_t cnt,loff_t *offt)
{unsigned char value = 0;struct key_dev *key1 = filp->private_data;if(gpio_get_value(key1->key_gpio)==0)//0按下,否則沒按下{while(gpio_get_value(key1->key_gpio)==0);//等待按鍵釋放,相當于判斷上升沿觸發atomic_set(&key1->key_value,KEY_VALUE);//原子操作 數據保護}else {                                    //未按下atomic_set(&key1->key_value,KEY_NOVALUE);}value = atomic_read(&key1->key_value);__copy_to_user(buf,&value,sizeof(value));return 0;
}
./APP /dev/pgled 1&static struct file_operations pgkey_fops={.owner=THIS_MODULE,.read=pgkey_read,.open=pgkey_open,.release=pgkey_release,
};static int __init pgkey_init(void)
{atomic_set(&key.key_value,KEY_NOVALUE);//原子操作,鎖設置 值為0,說明未按下// spin_lock_init(&key.lock_spin);//自旋// sema_init(&key.sem,1);//信號量//mutex_init(&key.lock_huci);//互斥體/*注冊*//*1.設備號*/if(key.major){key.key_hao = MKDEV(key.major,0);register_chrdev_region(key.key_hao, 1, KEY_NAME);//主動注冊}else{alloc_chrdev_region(&key.key_hao, 0, 1, KEY_NAME);//自動注冊}printk("major = %d,minor = %d",MAJOR(key.key_hao),MINOR(key.key_hao));/*2.注冊函數*/key.cdev.owner = THIS_MODULE;cdev_init(&key.cdev,&pgkey_fops);cdev_add(&key.cdev,key.key_hao,1);/*3.節點申請*/ key.class = class_create(THIS_MODULE,KEY_NAME);key.device = device_create(key.class, NULL,key.key_hao, NULL,KEY_NAME);/*4.具體實現*/  return 0;
}
static void  __exit pgkey_exit(void)
{gpio_free(key.key_gpio);//釋放gpiocdev_del(&key.cdev);//先刪除設備unregister_chrdev_region(key.key_hao,1);//刪除設備號device_destroy(key.class,key.key_hao);//先刪除和設備第關系class_destroy(key.class);//再刪除類}
./APP /dev/pgled 1&/*驅動入口和出口*/
module_init(pgkey_init);
module_exit(pgkey_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

應用:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>int main(unsigned char argc,unsigned char *argv[])
{int rel = 0,fd = 0;unsigned char *filename,read_buff[1];filename = argv[1];if(argc != 2){printf("WARNING!\r\n");return -1;}fd = open(filename,O_RDWR);if(fd<0) {printf("open file error\r\n");return -1;}while(1){read(fd,read_buff,1);if(read_buff[0]==1){printf(" 按下了! \r\n");}}return 0;}

四,內核定時器

1.關于定時器的有關概念

1.1 節拍HZ

??硬件定時器提供時鐘源,時鐘源的頻率可以設置,設置好以后就能周期性的產生中斷,系統時鐘定時中斷來計時,中斷的這個頻率就是系統頻率,稱為節拍,單位是HZ,比如100HZ,就是一秒有100個中斷產生。

1.2 jiffies

??linux內核中使用全局變量jiffies來記錄系統從啟動以來的節拍數,系統啟動的時候會將其初始化為0,然后系統運行,就開始計數。有32位的和64位的,內核中設置時間,比如想設置定時兩秒,那么目標時間=jiffies(此時的節拍數)+(2*節拍數HZ),當現在的節拍數jiffies大于目標時間,就認為到達設定時間兩秒。

在這里插入圖片描述

2.定時器實驗

??能夠用定時器控制led燈的閃爍頻率,并且能夠開關定時器,修改定時器周期。static void led_timer_function(unsigned long arg)定時器調回函數中,unsigned long arg是通用的參數傳遞機制,傳遞的是用戶定義的數據,將結構體指針&led強制轉化為unsigned long ,放到led.timer.data中,在放到arg中,意思就是arg傳遞的是led結構體的數據。

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <linux/of_gpio.h>
#include <linux/cdev.h>
#include <linux/kdev_t.h>
#include <linux/device.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/fs.h>  
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/slab.h>
#include <linux/jiffies.h>
#include <linux/ioctl.h>#define TIMER_NAME "led_timer"#define CLOSE_TIMER_CMD _IO(0xef, 1)  //1設置為關閉
#define OPEN_TIMER_CMD _IO(0xef, 2)  //2設置為開
#define PERIOD_TIMER_CMD _IOW(0xef, 3,int)  //3設置修改周期struct led_dev{struct class *class;struct device *device;struct device_node *nd;struct cdev cdev;dev_t led_hao;int major;//主設備號int minor;//次設備號int led_gpio;//led的gpioint timer_period;//定時器周期  利用原子操作保護atomic_t lock_yuan;//原子操作struct timer_list timer;//定義定時器};
struct led_dev led;
static int pgled_open(struct inode *innode,struct file *filp)
{filp->private_data = &led;//將led結構體數據設為私有數據return 0;
}
static int pgled_release(struct inode *innode,struct file *filp)
{return 0;
}
static long timer_ioctl(struct file *filp, unsigned int cmd , unsigned long arg)
{int ret = 0;struct led_dev *led_ioctl = (struct led_dev*)filp->private_data;int period =led_ioctl->timer_period;switch (cmd){case CLOSE_TIMER_CMD://關閉定時器del_timer_sync(&led_ioctl->timer);break;case OPEN_TIMER_CMD://打開定時器mod_timer(&led_ioctl->timer, jiffies + msecs_to_jiffies(led_ioctl->timer_period));break; case PERIOD_TIMER_CMD://從新配置定時器時間ret = __copy_from_user(&period, (int *)arg, sizeof(int));//這個arg是輸入第周期值。printk("111period =%d, led_ioctl->timer_period =%d,led.timer_period=%d\r\n",period,led_ioctl->timer_period,led.timer_period);led_ioctl->timer_period =  period;mod_timer(&led_ioctl->timer, jiffies + msecs_to_jiffies(led_ioctl->timer_period));printk("222period =%d, led_ioctl->timer_period =%d,led.timer_period=%d\r\n",period,led_ioctl->timer_period,led.timer_period);break;         default:break;}return 0;
}
static struct file_operations pgled_fops={.owner=THIS_MODULE,.unlocked_ioctl= timer_ioctl,.open=pgled_open,.release=pgled_release,};
static void led_timer_function(unsigned long arg)//定時結束后會執行第操作,
{struct led_dev *led_timer = (struct led_dev*)arg;//這個arg和上面的不一樣,上面是中端輸入數據的首地址,這個數據//是整形變量周期值,不是輸入的第一個數據,而這個是結構體變量led首地址static int status = 1;status = !status;gpio_set_value(led_timer->led_gpio,status);mod_timer(&led_timer->timer, jiffies + msecs_to_jiffies(led_timer->timer_period));//讓定時器再從新加載}
static int __init pgled_init(void)
{int ret =0;led.nd = of_find_node_by_path("/gpioled");//在設備樹中獲取節點led.led_gpio = of_get_named_gpio(led.nd,"led-gpio", 0);//得到gpio引腳ret = gpio_direction_output(led.led_gpio,1);//設置GPIO1-03為輸出,并且設置為1,高點平關閉if(ret == 0){printk("從設備樹讀取節點和gpio正確\r\n");}/*注冊*//*1.設備號*/if(led.major){led.led_hao = MKDEV(led.major,0);register_chrdev_region(led.led_hao, 1, TIMER_NAME);//主動注冊}else{alloc_chrdev_region(&led.led_hao, 0, 1, TIMER_NAME);//自動注冊}printk("major = %d,minor = %d",MAJOR(led.led_hao),MINOR(led.led_hao));/*2.注冊函數*/led.cdev.owner = THIS_MODULE;cdev_init(&led.cdev,&pgled_fops);cdev_add(&led.cdev,led.led_hao,1);/*3.節點申請*/ led.class = class_create(THIS_MODULE,TIMER_NAME);led.device = device_create(led.class, NULL,led.led_hao, NULL,TIMER_NAME);/*初始化定時器*/led.timer_period=1000;init_timer(&led.timer);//初始化定時器led.timer.function = led_timer_function;led.timer.expires = jiffies + msecs_to_jiffies(led.timer_period);led.timer.data = (unsigned long)&led;add_timer(&led.timer);//添加定時器return 0;
}static void  __exit pgled_exit(void)
{gpio_set_value(led.led_gpio,1);del_timer(&led.timer);gpio_free(led.led_gpio);cdev_del(&led.cdev);//先刪除設備unregister_chrdev_region(led.led_hao,1);//刪除設備號device_destroy(led.class,led.led_hao);//先刪除和設備第關系class_destroy(led.class);//再刪除類}/*驅動入口和出口*/
module_init(pgled_init);
module_exit(pgled_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("wyt");

應用:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>#define CLOSE_TIMER_CMD _IO(0xef, 1)  //1設置為關閉
#define OPEN_TIMER_CMD _IO(0xef, 2)  //2設置為開
#define PERIOD_TIMER_CMD _IOW(0xef, 3,int)  //3設置修改周期int main(unsigned char argc,unsigned char *argv[])
{int rel = 0,fd = 0,arg = 0;int cmd = 0;unsigned char *filename,str[6];filename = argv[1];fd = open(filename,O_RDWR);if(fd<0) printf("open file error\r\n");while(1){printf("INPUT CMD:\r\n");rel = scanf("%d",&cmd);if(rel!=1){gets(str);}switch(cmd){case 1:ioctl(fd,CLOSE_TIMER_CMD,&arg);break;case 2:ioctl(fd,OPEN_TIMER_CMD,&arg);break;case 3:printf("input period:");rel = scanf("%d",&arg);printf("arg1 = %d",arg);if(rel!=1){gets(str);}ioctl(fd,PERIOD_TIMER_CMD,&arg);break;case 4:return 0;default:break;            }}rel = close(fd);if(rel<0) printf("close in  APP error\r\n");return 0;}

五,相關問題

1.pin和gpio

??PIN 是芯片或電路板上的物理引腳,用于連接芯片與外部電路。GPIO 是一種通用的引腳功能,允許引腳通過軟件配置為輸入或輸出模式。在輸入模式下,GPIO 可以讀取外部信號;在輸出模式下,GPIO 可以驅動外部設備。pin是個大類,gpio是其中的一部分,比如pin可以設置為多種功能(如 GPIO、UART、I2C、SPI 等)。

2.depmod作用

??depmod: Linux 系統中用于生成模塊依賴關系文件的工具。會掃描 /lib/modules/<內核版本>/ 目錄下的所有內核模塊,分析它們之間的依賴關系,依賴關系包括模塊之間的符號引用(如函數、變量等)。

3.得到gpio后,使用request申請的作用

??request函數用于申請 GPIO 引腳的使用權,它的主要作用是確保 GPIO 引腳不會被多個驅動程序或模塊同時使用,從而避免資源沖突,具體就是標記 GPIO 引腳為“已使用”狀態,防止其他驅動程序或模塊重復使用該引腳。

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

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

相關文章

數據庫的高階知識

目錄 一、case when二、幾種常見的嵌套查詢2.1 比較運算符2.2 ANY/ALL 關鍵詞2.3 in 關鍵詞2.4 EXISTS關鍵詞2.5 in和exists的異同點 三、開窗函數 數據庫的基本知識 數據庫的高階知識 一、case when 在實際工作中&#xff0c;經常會涉及以下兩類問題&#xff1a; 數據的映射…

【Kubernetes】Service 的類型有哪些?ClusterIP、NodePort 和 LoadBalancer 的區別?

在 Kubernetes 中&#xff0c;Service 是一種抽象的方式&#xff0c;用于將一組 Pod 進行連接并暴露給外部或集群內部訪問。它的主要目的是通過提供穩定的 IP 地址和端口來允許其他服務或客戶端與一組 Pod 進行通信。 Service 類型 Kubernetes 中 Service 有四種主要類型&…

MapReduce處理數據流程

&#xff08;一&#xff09;Shuffle MapReduce中的Shuffle過程指的是在Map方法執行后、Reduce方法執行前對數據進行分區排序的階段 &#xff08;二&#xff09;處理流程 1. 首先MapReduce會將處理的數據集劃分成多個split&#xff0c;split劃分是邏輯上進行劃分&#xff0c;…

OrioleDB: 新一代PostgreSQL存儲引擎

PostgreSQL 12 引入了可插拔式的表存儲方法接口&#xff0c;允許為不同的表選擇不同的存儲機制&#xff0c;例如用于 OLTP 操作的堆表&#xff08;HEAP、默認&#xff09;、用于 OLAP 操作的列式表&#xff08;Citus&#xff09;&#xff0c;以及用于超快速搜索處理的內存表。 …

電腦自動關機故障維修案例分享

電腦基本配置&#xff1a; C P U: AMD A10 9700 內存&#xff1a;8G 硬盤&#xff1a;金邦512G固態硬盤 主板&#xff1a;華碩 A320M-F 顯卡&#xff1a;集成&#xff08;核心顯卡&#xff09; 操作系統&#xff1a;Win10專業版 故障描述&#xff1a; 使用一段時間會黑屏…

JVM垃圾收集器相關面試題(1)

垃圾收集與內存管理摘要 一.核心垃圾收集算法對比 算法原理優點缺點適用場景標記-清除兩次遍歷&#xff08;標記存活對象→清除未標記對象&#xff09;實現簡單內存碎片化、雙遍歷效率低老年代&#xff08;結合整理&#xff09;標記-復制內存對半分&#xff0c;存活對象復制到…

棧(LIFO)算法題

1.刪除字符串中所有相鄰的重復字符 注意&#xff0c;我們需要重復處理&#xff0c;而不是處理一次相鄰的相同元素就結束了。對示例來說&#xff0c;如果只進行一次處理&#xff0c;結果為aaca&#xff0c;但是處理之后又出現了相鄰的重復元素&#xff0c;我們還得繼續處理&…

conda的基本使用及pycharm里設置conda環境

創建conda環境 conda create --name your_env_name python3.8 把your_env_name換成實際的conda環境名稱&#xff0c;python后邊的根據自己的需要&#xff0c;選擇python的版本。 激活conda環境 conda activate your_env_name 安裝相關的包、庫 conda install package_name …

Python基于深度學習的多模態人臉情緒識別研究與實現

一、系統架構設計 A[數據采集] --> B[預處理模塊] B --> C[特征提取] C --> D[多模態融合] D --> E[情緒分類] E --> F[系統部署] F --> G[用戶界面] 二、數據準備與處理 1. 數據收集 - 視頻數據&#xff1a;FER2013&#xff08;靜態圖像&#xff0…

synchronized與 Java內置鎖(未寫完)

文章目錄 一、 synchronized 關鍵字二、Java對象結構1. 對象頭2. 對象體3. 對齊字節4. 對象頭中的字段長度5. Mark Word 的結構信息6. 使用 JOL 工具查看對象的布局 三、Java 內置鎖機制3.1 內置鎖的演進過程1. 無鎖狀態2. 偏向鎖狀態3. 輕量級鎖狀態4. 重量級鎖狀態 一、 sync…

LLM(3): Transformer 架構

Transformer 架構是當前大語言模型的主力架構和基礎技術&#xff0c;本文以通俗易懂的方式&#xff0c;對此作簡要介紹。 1.4 介紹 Transformer 架構 大多數現代的大規模語言模型&#xff08;LLMs&#xff09;依賴于 Transformer 架構&#xff0c;這是一種在 2017 年的論文《…

11.【.NET 8 實戰--孢子記賬--從單體到微服務--轉向微服務】--微服務基礎工具與技術--Ocelot 網關--整合日志

網關作為微服務架構的入口&#xff0c;承載著各服務間的請求轉發與安全校驗&#xff0c;其日志信息尤為關鍵。通過整合網關日志&#xff0c;可以將分散在不同系統中的訪問記錄、錯誤提示和異常信息集中管理&#xff0c;為問題排查提供全景視角。在排查故障時&#xff0c;統一日…

88.HarmonyOS NEXT 性能監控與調試指南:構建高性能應用

溫馨提示&#xff1a;本篇博客的詳細代碼已發布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下載運行哦&#xff01; HarmonyOS NEXT 性能監控與調試指南&#xff1a;構建高性能應用 文章目錄 HarmonyOS NEXT 性能監控與調試指南&#xff1a;構建高性能應用1. 性能監…

012---狀態機的基本知識

1. 摘要 文章為學習記錄。主要介紹狀態機概述、狀態轉移圖、狀態編碼、狀態機寫法、狀態機代碼示例。 2. 狀態機概述 狀態機 &#xff08;Finite State Machine&#xff09;&#xff0c;也稱為同步有限狀態機&#xff0c;用于描述有先后順序或時序規律的事情。 “同步”&…

deepseek+kimi做ppt教程記錄

1.首先注冊deepseek和kimi deepseek官網&#xff1a;https://chat.deepseek.com/ kimi官網&#xff1a;https://kimi.moonshot.cn/ 以下以一篇工作總結報告為例 2.使用deepseek生成ppt大綱 讓deepseek生成kimi生成ppt所需要的內容時&#xff0c;需要注意提示詞內容&#xff0c;…

Java Module介紹

Java模塊系統自Java 9開始引入&#xff0c;旨在提供更強大的封裝機制、清晰的依賴關系定義以及可靠的配置。Java平臺本身也被模塊化了&#xff0c;提供了多個核心模塊以及其他用于支持不同功能的模塊。以下是一些重要的Java標準模塊&#xff1a; java.base - 這是最基礎的模塊…

SOME/IP:用Python實現協議訂閱、Offer、訂閱ACK與報文接收

文章目錄 前言一、代碼層次二、詳細代碼1. eth_scapy_sd.py2、eth_scapy_someip.py3、network_define.py4、packet_define.py5、unpack_define.py6、someip_controller.py 前言 1、需要pip安裝scapy庫 2、需要修改根據實際情況配置network_define.py 3、執行someip_controller…

【Linux內核系列】:文件系統收尾以及軟硬鏈接詳解

&#x1f525; 本文專欄&#xff1a;Linux &#x1f338;作者主頁&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客勵志語錄&#xff1a; 世界上只有一種個人英雄主義&#xff0c;那么就是面對生活的種種失敗卻依然熱愛著生活 內容回顧 那么在之前的學習中&#xff0c;我們…

最新版Chrome瀏覽器加載ActiveX控件技術--allWebPlugin中間件一鍵部署瀏覽器擴展

allWebPlugin簡介 allWebPlugin中間件是一款為用戶提供安全、可靠、便捷的瀏覽器插件服務的中間件產品&#xff0c;致力于將瀏覽器插件重新應用到所有瀏覽器。它將現有ActiveX控件直接嵌入瀏覽器&#xff0c;實現插件加載、界面顯示、接口調用、事件回調等。支持Chrome、Firefo…

基于SpringBoot和MybatisPlus實現通用Controller

基于SpringBoot和MybatisPlus實現通用Controller&#xff0c;只需要創建實體類和mapper接口&#xff0c;單表增刪改查接口就已經實現&#xff0c;提升開發效率 1.定義通用controller package com.xian.controller;import cn.hutool.core.map.MapUtil; import com.baomidou.my…