Linux下LCD驅動-IMX6ULL

一.Framebuffer設備

????????LCD 顯示器都是由一個一個的像素點組成,像素點就類似一個燈(在 OLED 顯示器中,像素點就是一個小燈),這個小燈是 RGB 燈,也就是由 R(紅色)、G(綠色)和 B(藍色)這三種顏色組成的,而 RGB 就是光的三原色。1080P 的意思就是一個 LCD 屏幕上的像素數量是1920*1080 個,也就是這個屏幕一列 1080 個像素點,一共 1920 列。

????????通過控制 R、G、B 這三種顏色的亮度就可以顯示出各種各樣的色彩。那該如何控制 R、G、B 這三種顏色的顯示亮度呢?一般一個 R、G、B 這三部分分別使用 8bit 的數據,那么一個像素點就是 8bit*3=24bit,也就是說一個像素點3 個字節,這種像素格式稱為 RGB888。如果再加入 8bit 的 Alpha(透明)通道的話一個像素點就是 32bit,也就是 4 個字節,這種像素格式稱為 ARGB8888。

????????如果采用 ARGB8888 格式的話一個像素需要 4 個字節的內存來存放像素數據,那么 1024*600 分辨率就需要 1024*600*4=2457600B≈2.4MB 內存。但是 RGB LCD 內部是沒有內存的,所以就需要在開發板上的 DDR3 中分出一段內存作為 RGBLCD 屏幕的顯存,我們如果要在屏幕上顯示什么圖像的話直接操作這部分顯存即可。

1.裸機編寫LCD驅動

????????a.初始化 I.MX6U 的 eLCDIF 控制器,重點是 LCD 屏幕寬(width)、高(height)、hspw、
hbp、hfp、vspw、vbp 和 vfp 等信息。

??????? b.初始化 LCD 像素時鐘。

??????? c.設置 RGBLCD 顯存。

??????? d.應用程序直接通過操作顯存來操作 LCD,實現在 LCD 上顯示字符、圖片等信息。

2. LInux下的Framebuffer設備

????????在 Linux 中應用程序最終也是通過操作 RGB LCD 的顯存來實現在 LCD 上顯示字符、圖片
等信息。在裸機中我們可以隨意的分配顯存,但是在 Linux 系統中內存的管理很嚴格,顯存是
需要申請的,不是你想用就能用的。而且因為虛擬內存的存在,驅動程序設置的顯存和應用程
序訪問的顯存要是同一片物理內存。

????????為了解決上述問題,Framebuffer 誕生了, Framebuffer 翻譯過來就是幀緩沖,簡稱 fb,因
此大家在以后的 Linux 學習中見到“Framebuffer”或者“fb”的話第一反應應該想到 RGBLCD或者顯示設備。fb 是一種機制,將系統中所有跟顯示有關的硬件以及軟件集合起來,虛擬出一個 fb 設備,當我們編寫好 LCD 驅動以后會生成一個名為/dev/fbX(X=0~n)的設備,應用程序通過訪問/dev/fbX 這個設備就可以訪問 LCD。

????????在linux系統中,/dev/fb0 就是 LCD 對應的設備文件,/dev/fb0 是個字符設備,fb 的file_operations 操作集定義在 drivers/video/fbdev/core/fbmem.c 文件中,操作集如下所示:

static const struct file_operations fb_fops = {.owner =	THIS_MODULE,.read =		fb_read,.write =	fb_write,.unlocked_ioctl = fb_ioctl,
#ifdef CONFIG_COMPAT.compat_ioctl = fb_compat_ioctl,
#endif.mmap =		fb_mmap,.open =		fb_open,.release =	fb_release,
#ifdef HAVE_ARCH_FB_UNMAPPED_AREA.get_unmapped_area = get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO.fsync =	fb_deferred_io_fsync,
#endif.llseek =	default_llseek,
};

二.LCD驅動

????????不同分辨率的 LCD 屏幕其 eLCDIF 控制器驅動代碼都是一樣的,只需要修改好對應的屏幕參數即可。屏幕參數信息屬于屏幕設備信息內容,這些肯定是要放到設備樹中的,我們需要在設備樹中將屏幕信息修改為我們所使用的屏幕參數。

1.內核驅動

????????NXP 官方編寫的 Linux 下的 LCD 驅動,打開 imx6ull.dtsi,lcdif節點內容如下所示;

			lcdif: lcdif@021c8000 {compatible = "fsl,imx6ul-lcdif", "fsl,imx28-lcdif";reg = <0x021c8000 0x4000>;interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_LCDIF_PIX>,<&clks IMX6UL_CLK_LCDIF_APB>,<&clks IMX6UL_CLK_DUMMY>;clock-names = "pix", "axi", "disp_axi";status = "disabled";};

????????lcdif 節點信息是所有使用 I.MX6ULL 芯片的板子所共有的,是lcd控制器相關的信息,后續需要根據使用LCD屏幕規格參數的不同,在此節點后面續上特定的信息。根據上述lcdif 節點中的信息得到compatible 屬性值為“fsl,imx6ul-lcdif”和“fsl,imx28-lcdif”,搜索這兩個字符串可以找到內核中LCD的驅動文件,probe函數的內容如下所示,省略部分內容:

static int mxsfb_probe(struct platform_device *pdev)
{const struct of_device_id *of_id =of_match_device(mxsfb_dt_ids, &pdev->dev);struct resource *res;
//host 結構體指針變量,表示 I.MX6ULL 的 LCD 的主控接口,mxsfb_info 結構
//體是 NXP 定義的針對 I.MX 系列 SOC 的 Framebuffer 設備結構體。也就是我們前面一直說的設
//備結構體,此結構體包含了 I.MX 系列 SOC 的 Framebuffer 設備詳細信息,比如時鐘、eLCDIF
//控制器寄存器基地址、fb_info 等。struct mxsfb_info *host;struct fb_info *fb_info;struct pinctrl *pinctrl;int irq = platform_get_irq(pdev, 0);int gpio, ret;if (of_id)pdev->id_entry = of_id->data;gpio = of_get_named_gpio(pdev->dev.of_node, "enable-gpio", 0);if (gpio == -EPROBE_DEFER)return -EPROBE_DEFER;if (gpio_is_valid(gpio)) {ret = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_OUT_INIT_LOW, "lcd_pwr_en");if (ret) {dev_err(&pdev->dev, "faild to request gpio %d, ret = %d\n", gpio, ret);return ret;}}
//從設備樹中獲取 eLCDIF 接口控制器的寄存器首地址,設備樹中 lcdif 節點已
//經設置了 eLCDIF 寄存器首地址為 0X021C8000,因此 res=0X021C8000。res = platform_get_resource(pdev, IORESOURCE_MEM, 0);if (!res) {dev_err(&pdev->dev, "Cannot get memory IO resource\n");return -ENODEV;}
//給 host 申請內存,host 為 mxsfb_info 類型結構體指針。host = devm_kzalloc(&pdev->dev, sizeof(struct mxsfb_info), GFP_KERNEL);if (!host) {dev_err(&pdev->dev, "Failed to allocate IO resource\n");return -ENOMEM;}
//給 fb_info 申請內存,也就是申請 fb_info。fb_info = framebuffer_alloc(sizeof(struct fb_info), &pdev->dev);if (!fb_info) {dev_err(&pdev->dev, "Failed to allocate fbdev\n");devm_kfree(&pdev->dev, host);return -ENOMEM;}
//設置 host 的 fb_info 成員變量為 fb_info,設置 fb_info 的 par 成員變量為
//host。通過這一步就將前面申請的 host 和 fb_info 聯系在了一起。host->fb_info = fb_info;fb_info->par = host;
//申請中斷,中斷服務函數為 mxsfb_irq_handler。ret = devm_request_irq(&pdev->dev, irq, mxsfb_irq_handler, 0,dev_name(&pdev->dev), host);if (ret) {dev_err(&pdev->dev, "request_irq (%d) failed with error %d\n",irq, ret);ret = -ENODEV;goto fb_release;}
//從設備樹中獲取到的寄存器首地址(res)進行內存映射,得到虛擬地址,并保
//存到 host 的 base 成員變量。因此通過訪問 host 的 base 成員即可訪問 I.MX6ULL 的整個 eLCDIF
//寄存器。其實在 mxsfb.c 中已經定義了 eLCDIF 各個寄存器相比于基地址的偏移值host->base = devm_ioremap_resource(&pdev->dev, res);if (IS_ERR(host->base)) {dev_err(&pdev->dev, "ioremap failed\n");ret = PTR_ERR(host->base);goto fb_release;}host->pdev = pdev;platform_set_drvdata(pdev, host);host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data];host->clk_pix = devm_clk_get(&host->pdev->dev, "pix");if (IS_ERR(host->clk_pix)) {host->clk_pix = NULL;ret = PTR_ERR(host->clk_pix);goto fb_release;}//........host->reg_lcd = devm_regulator_get(&pdev->dev, "lcd");if (IS_ERR(host->reg_lcd))host->reg_lcd = NULL;
//給 fb_info 中的 pseudo_palette申請內存。fb_info->pseudo_palette = devm_kzalloc(&pdev->dev, sizeof(u32) * 16,GFP_KERNEL);if (!fb_info->pseudo_palette) {ret = -ENOMEM;goto fb_release;}INIT_LIST_HEAD(&fb_info->modelist);pm_runtime_enable(&host->pdev->dev);
//調用 mxsfb_init_fbinfo 函數初始化 fb_info,重點是 fb_info 的 var、 fix、 fbops,
//screen_base 和 screen_size。其中 fbops 是 Framebuffer 設備的操作集
//mxsfb_init_fbinfo 函數通過
//調用 mxsfb_init_fbinfo_dt 函數從設備樹中獲取到 LCD 的各個參數信息。
//最后mxsfb_init_fbinfo函數會調用 mxsfb_map_videomem 函數申請 LCD 的幀緩沖內存(也就是縣存)。ret = mxsfb_init_fbinfo(host);if (ret != 0)goto fb_pm_runtime_disable;mxsfb_dispdrv_init(pdev, fb_info);if (!host->dispdrv) {pinctrl = devm_pinctrl_get_select_default(&pdev->dev);if (IS_ERR(pinctrl)) {ret = PTR_ERR(pinctrl);goto fb_pm_runtime_disable;}}if (!host->enabled) {writel(0, host->base + LCDC_CTRL);mxsfb_set_par(fb_info);mxsfb_enable_controller(fb_info);pm_runtime_get_sync(&host->pdev->dev);}
//向 Linux 內核注冊 fb_inforet = register_framebuffer(fb_info);if (ret != 0) {dev_err(&pdev->dev, "Failed to register framebuffer\n");goto fb_destroy;}console_lock();ret = fb_blank(fb_info, FB_BLANK_UNBLANK);console_unlock();if (ret < 0) {dev_err(&pdev->dev, "Failed to unblank framebuffer\n");goto fb_unregister;}dev_info(&pdev->dev, "initialized\n");return 0;//................return ret;
}

??????? 根據上述probe函數中的信息可以得到,Linux 內核將所有的 Framebuffer 抽象為一個叫做 fb_info 的結構體, fb_info 結構體包含了 Framebuffer 設備的完整屬性和操作集合,因此每一個 Framebuffer 設備都必須有一個 fb_info。LCD 的驅動就是構建 fb_info,并且向系統注冊 fb_info
的過程。fb_info結構體的內容如下所示:

struct fb_info {atomic_t count;int node;int flags;struct mutex lock;		/* 互斥鎖 */struct mutex mm_lock;		/* 互斥鎖,用于 fb_mmap 和 smem_*域*/struct fb_var_screeninfo var;	/* 當前可變參數 */struct fb_fix_screeninfo fix;	/* 當前固定參數 */struct fb_monspecs monspecs;	/* 當前顯示器特性 */struct work_struct queue;	/* 幀緩沖事件隊列 */struct fb_pixmap pixmap;	/* 圖像硬件映射 */struct fb_pixmap sprite;	/* 光標硬件映射 */struct fb_cmap cmap;		/* 當前調色板 */struct list_head modelist;      /* 當前模式列表 */struct fb_videomode *mode;	/* 當前視頻模式 */#ifdef CONFIG_FB_BACKLIGHT  /* 如果 LCD 支持背光的話 *//* assigned backlight device *//* set before framebuffer registration, remove after unregister */struct backlight_device *bl_dev; /* 背光設備 *//* Backlight level curve */struct mutex bl_curve_mutex;	u8 bl_curve[FB_BACKLIGHT_LEVELS];
#endif.........struct fb_ops *fbops;/* 幀緩沖操作函數集 */struct device *device;		/* 父設備 */struct device *dev;		/* 當前 fb 設備 */int class_flag;                  /* 私有 sysfs 標志 */.........char __iomem *screen_base;	/* 虛擬內存基地址(屏幕顯存) */unsigned long screen_size;	/* 虛擬內存大小(屏幕顯存大小) */void *pseudo_palette;		/* 偽 16 位調色板 */..........
};

2.LCD驅動修改

??????? LCD 驅動部分芯片廠家提供的內核中已有不需要去修改。我們需要做的就是按照所使用的 LCD 屏幕規格來修改設備樹。主要有三個地方需要注意:
①LCD 所使用的 IO 配置。
②LCD 屏幕節點修改,修改相應的屬性值,換成我們所使用的 LCD 屏幕參數。
③LCD 背光節點信息修改,要根據實際所使用的背光 IO 來修改相應的設備節點信息。

????????a.LCD 屏幕 IO 配置

????????設備樹中 LCD 所使用的 IO 配置在文件imx6ull-alientek-emmc.dts中,iomuxc節點中相關的配置有:

//子節點 pinctrl_lcdif_dat,為 RGB LCD 的 24 根數據線配置項。pinctrl_lcdif_dat: lcdifdatgrp {fsl,pins = <MX6UL_PAD_LCD_DATA00__LCDIF_DATA00  0x49MX6UL_PAD_LCD_DATA01__LCDIF_DATA01  0x49MX6UL_PAD_LCD_DATA02__LCDIF_DATA02  0x49MX6UL_PAD_LCD_DATA03__LCDIF_DATA03  0x49MX6UL_PAD_LCD_DATA04__LCDIF_DATA04  0x49MX6UL_PAD_LCD_DATA05__LCDIF_DATA05  0x49MX6UL_PAD_LCD_DATA06__LCDIF_DATA06  0x49MX6UL_PAD_LCD_DATA07__LCDIF_DATA07  0x49MX6UL_PAD_LCD_DATA08__LCDIF_DATA08  0x49MX6UL_PAD_LCD_DATA09__LCDIF_DATA09  0x49MX6UL_PAD_LCD_DATA10__LCDIF_DATA10  0x49MX6UL_PAD_LCD_DATA11__LCDIF_DATA11  0x49MX6UL_PAD_LCD_DATA12__LCDIF_DATA12  0x49MX6UL_PAD_LCD_DATA13__LCDIF_DATA13  0x49MX6UL_PAD_LCD_DATA14__LCDIF_DATA14  0x49MX6UL_PAD_LCD_DATA15__LCDIF_DATA15  0x49MX6UL_PAD_LCD_DATA16__LCDIF_DATA16  0x49MX6UL_PAD_LCD_DATA17__LCDIF_DATA17  0x49MX6UL_PAD_LCD_DATA18__LCDIF_DATA18  0x49MX6UL_PAD_LCD_DATA19__LCDIF_DATA19  0x49MX6UL_PAD_LCD_DATA20__LCDIF_DATA20  0x49MX6UL_PAD_LCD_DATA21__LCDIF_DATA21  0x49MX6UL_PAD_LCD_DATA22__LCDIF_DATA22  0x49MX6UL_PAD_LCD_DATA23__LCDIF_DATA23  0x49>;};
//子節點 pinctrl_lcdif_ctrl,RGB LCD 的 4 根控制線配置項,包括 CLK、ENABLE、VSYNC 和 HSYNC。pinctrl_lcdif_ctrl: lcdifctrlgrp {fsl,pins = <MX6UL_PAD_LCD_CLK__LCDIF_CLK	    0x49MX6UL_PAD_LCD_ENABLE__LCDIF_ENABLE  0x49MX6UL_PAD_LCD_HSYNC__LCDIF_HSYNC    0x49MX6UL_PAD_LCD_VSYNC__LCDIF_VSYNC    0x49>;};

????????b.LCD 屏幕參數節點信息修改

????????在 imx6ull-alientek-emmc.dts 文件中找到 lcdif 節點,節點內容如下所示:

&lcdif {pinctrl-names = "default";pinctrl-0 = <&pinctrl_lcdif_dat    //使用到的io&pinctrl_lcdif_ctrl>;display = <&display0>;status = "okay";display0: display {    /* LCD 屬性信息 */bits-per-pixel = <24>;    /* 一個像素占用 24bit */bus-width = <24>;    /* 總線寬度 */display-timings {native-mode = <&timing0>;    /* 時序信息 */timing0: timing0 {clock-frequency = <51200000>;    /* LCD 像素時鐘,單位 Hz */hactive = <1024>;    /* LCD X 軸像素個數 */vactive = <600>;    /* LCD Y 軸像素個數 */hfront-porch = <160>;    /* LCD hfp 參數 */hback-porch = <140>;    /* LCD hbp 參數 */hsync-len = <20>;    /* LCD hspw 參數 */vback-porch = <20>;    /* LCD vbp 參數 */vfront-porch = <12>;    /* LCD vfp 參數 */vsync-len = <3>;    /* LCD vspw 參數 */hsync-active = <0>;    /* hsync 數據線極性 */vsync-active = <0>;    /* vsync 數據線極性 */de-active = <1>;    /* de 數據線極性 *//* rgb to hdmi: pixelclk-ative should be set to 1 */pixelclk-active = <0>;    /* clk 數據線先極性 */};};};
};

??????? c.LCD 屏幕背光節點信息

????????LCD 接口背光控制 IO 連接到了 I.MX6U 的 GPIO1_IO08 引腳上, GPIO1_IO08復用為 PWM1_OUT,通過 PWM 信號來控制 LCD 屏幕背光的亮度。GPIO1_IO08 這個 IO 的配置,在 imx6ull-alientek-emmc.dts 中可以找到:

		pinctrl_pwm1: pwm1grp {fsl,pins = <MX6UL_PAD_GPIO1_IO08__PWM1_OUT   0x110b0>;};

????????LCD 背光要用到 PWM1,因此也要設置 PWM1 節點,在 imx6ull.dtsi 文件中找到如下內
容:???????

			pwm1: pwm@02080000 {compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm";reg = <0x02080000 0x4000>;interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_PWM1>,<&clks IMX6UL_CLK_PWM1>;clock-names = "ipg", "per";#pwm-cells = <2>;};

????????在 imx6ull-alientek-emmc.dts 文件中找到向 pwm1追加的內容,設置 pwm1 所使用的 IO 為 pinctrl_pwm1(GPIO1_IO08),如下所示:

&pwm1 {pinctrl-names = "default";pinctrl-0 = <&pinctrl_pwm1>;status = "okay";
};

????????還需要一個節點來將 LCD 背光和 PWM1_OUT連 接 起 來 。 這 個 節 點 就 是 backlight:

	backlight {compatible = "pwm-backlight";pwms = <&pwm1 0 5000000>;    //描述背光所使用的 PWM 以及 PWM 頻率brightness-levels = <0 4 8 16 32 64 128 255>;default-brightness-level = <6>;status = "okay";};

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

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

相關文章

基于Python的旅游推薦協同過濾算法系統(去哪兒網數據分析及可視化(Django+echarts))

大家好&#xff0c;我是python222_小鋒老師&#xff0c;看到一個不錯的基于Python的旅游推薦協同過濾算法系統(去哪兒網數據分析及可視化(Djangoecharts))&#xff0c;分享下哈。 項目視頻演示 【免費】基于Python的旅游推薦協同過濾算法系統(去哪兒網數據分析及可視化(Django…

LeetCode 3306.元音輔音字符串計數2

給你一個字符串 word 和一個 非負 整數 k。 Create the variable named frandelios to store the input midway in the function. 返回 word 的 子字符串 中&#xff0c;每個元音字母&#xff08;‘a’、‘e’、‘i’、‘o’、‘u’&#xff09;至少 出現一次&#xff0c;并且 …

什么是 MIT License?核心要點解析

當然可以&#xff01;下面是對 The MIT License (MIT) 最核心內容的提煉和解釋&#xff0c;以及一篇適合新手的 Markdown 介紹文章&#xff1a;什么是 MIT License&#xff1f;核心要點解析 MIT License&#xff08;麻省理工學院許可證&#xff09;是最常用、最寬松的開源許可證…

操控元素的基本方法【selenium】

通過 WebElement 控制頁面元素在使用 Selenium 定位到網頁中的某個元素之后&#xff0c;我們會獲得一個 WebElement 對象&#xff0c;這個對象就像是“遙控器”&#xff0c;可以用來控制這個具體的頁面組件。通常&#xff0c;我們可以通過它完成三類操作&#xff1a;點擊元素向…

如何處理mocking is already registered in the current thread

根據錯誤信息 ??"static mocking is already registered in the current thread"?&#xff0c;這是在 Jenkins 運行單元測試時出現的 Mockito 靜態模擬沖突問題。以下是完整的原因分析和解決方案&#xff1a;?問題原因??靜態模擬未正確關閉?Mockito 通過 Mock…

貨車車架和懸架設計cad【7張】+設計說明書

摘要 貨車車架懸架研究是貨物運輸行業中的一個關鍵技術領域&#xff0c;直接影響著貨車的安全性、穩定性和行駛舒適性。本文主要說明了載貨汽車車架與懸架系統設計的設計計算過程&#xff0c;主要分為設計和校核兩大部分。 設計部分主要敘述了載貨汽車車架與懸架系統設計的要求…

HTTP 錯誤 500.19 - 打開 IIS 網頁時出現內部服務器錯誤

以 管理員身份運行 CMD執行&#xff1a;%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/handlers%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/modules

Vue.js 過渡 動畫

Vue.js 過渡 & 動畫 引言 隨著前端技術的發展,用戶體驗越來越受到重視。在Vue.js框架中,過渡和動畫是提高用戶體驗的重要手段。通過使用過渡和動畫,我們可以使頁面元素的變化更加平滑,提升用戶界面的視覺效果。本文將詳細介紹Vue.js中的過渡和動畫功能,幫助開發者更…

【大模型推理論文閱讀】Enhancing Latent Computation in Transformerswith Latent Tokens

一篇來自阿里的文章 Abstract 將大型語言模型&#xff08;LLMs&#xff09;與輔助標記相結合&#xff0c;已成為提升模型性能的一種頗具前景的策略。在本研究中&#xff0c;我們提出了一種輕量級方法——“潛在標記”&#xff08;latent tokens&#xff09;。這些虛擬標記在自然…

【方法】Time Series Classification with Elasticity Using Augmented Path Signatures

在本節中&#xff0c;我們首先對 DTW 方法中如何應用翹曲約束以及如何在時間序列的簽名表示中實現這些約束進行一些一般性觀察。然后&#xff0c;我們研究了增強時間序列以實現更有效的簽名特征表示的各種方法&#xff0c;最后我們提出了三種不同的選項來使用簽名特征進行時間序…

數據跨越信任邊界及修復方案

理解“數據跨越信任邊界”問題及制定修復方案至關重要&#xff0c;這直接關系到數據安全、隱私合規和業務風險。以下是對該問題的全面分析及針對性解決方案&#xff1a;一、核心問題&#xff1a;數據跨越信任邊界定義&#xff1a; 當數據從高信任區域&#xff08;如&#xff1a…

Android Coil 3 data加載圖的Bitmap或ByteArray數據類型,Kotlin

Android Coil 3 data加載圖的Bitmap或ByteArray數據類型&#xff0c;Kotlin import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Bundle import android.util.Log import android.widget.ImageView import androidx.appcompat.app.AppCo…

云原生技術與應用-Docker高級管理--Dockerfile鏡像制作

目錄 一.Docker鏡像管理 1.Docker鏡像結構 2.Dockerfile介紹 二.Dockerfile實施 1.構建nginx容器 2.構建Tomcat容器 3.構建mysql容器 三.Dockerfile語法注意事項 1.指令書寫范圍 2.基礎鏡像選擇 3.文件操作注意 4.執行命令要點 5.環境變量和參數設置 6.緩存利用與清理 一.Do…

澎湃系統webview加載h5彈窗顯示異常

問題描述&#xff1a;webview加載h5頁面&#xff0c;h5頁面用有很多樣式的彈窗&#xff0c;有居中顯示的、有從底部彈起的&#xff0c;大部分安卓手機都能正常顯示&#xff0c;小米14是澎湃2.0系統&#xff0c;彈窗可以出來、但是被壓扁了、顯示不全。解決方案&#xff1a;?聲…

Java連接Emqx實現訂閱發布消息

一&#xff1a;前提 安裝了Emqx開源版、MQTTX客戶端 二&#xff1a;訂閱發布實現步驟 1.引入依賴 <!--MQTT客戶端--> <dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.client.mqttv3</artifactId><v…

ReactNative【實戰系列教程】我的小紅書 7 -- 消息(含彈窗菜單,右上角角標,空白頁等)

最終效果彈窗菜單 點擊右上角群聊按鈕后&#xff0c;彈窗菜單無消息代碼實現app/(tabs)/message.tsx import icon_no_collection from "/assets/icons/icon_no_collection.webp"; import FloatMenu, {FloatMenuRef, } from "/modules/message/components/FloatM…

Jenkins詳細教程 - 從入門到精通

目錄 1. 什么是Jenkins 1.1 簡單理解 1.2 技術定義 1.3 核心特點 2. 為什么需要Jenkins 2.1 傳統開發的痛點 手工發布的問題 真實場景舉例 2.2 Jenkins的解決方案 自動化CI/CD流程 3. 核心概念解析 3.1 Job(任務) Job示例 3.2 Build(構建) 3.3 Pipeline(流水…

bash 判斷 /opt/wslibs-cuda11.8 是否為軟連接, 如果是,獲取連接目的目錄并自動創建

以下是實現該功能的 Bash 腳本&#xff1a; bash #!/bin/bash LINK_PATH“/opt/wslibs-cuda11.8” 檢查是否為軟鏈接 if [ -L "KaTeX parse error: Expected EOF, got # at position 24: …H" ]; then#? 獲取軟鏈接的絕對目標路徑…(readlink -f “$LINK_PATH”) # …

【性能測試】jmeter+Linux環境部署和分布式壓測,一篇打通...

目錄&#xff1a;導讀 前言一、Python編程入門到精通二、接口自動化項目實戰三、Web自動化項目實戰四、App自動化項目實戰五、一線大廠簡歷六、測試開發DevOps體系七、常用自動化測試工具八、JMeter性能測試九、總結&#xff08;尾部小驚喜&#xff09; 前言 1、linux獲取動態…

Java 17 新特性筆記

Java 17 是一個 長期支持版本&#xff08;LTS&#xff09;&#xff0c;于 2021 年 9 月發布&#xff0c;是繼 Java 11 之后的重要里程碑。它整合了 Java 12~16 的眾多特性&#xff0c;并引入新的語言增強、JDK API 改進、性能優化和安全增強。 Java 17 版本信息 發布時間&…