热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

linux驱动移植LCD驱动分析

 一、LCD基础知识1.1LCD硬件原理在Mini2440裸机开发之LCD基础我们介绍了LCD的硬件原理,有兴趣的可以去看看,这里我们仅仅简述一下LCD的原理。下图是LCD示意图,

 一、LCD基础知识


1.1 LCD硬件原理

在Mini2440裸机开发之LCD基础我们介绍了LCD的硬件原理,有兴趣的可以去看看,这里我们仅仅简述一下LCD的原理。

下图是LCD示意图,里面的每个点就是一个像素点。它里面有一个电子枪,一边移动,一边发出各种颜色的光。用动态图表示如下:

电子枪是如何移动的?



  • 有一条CLK时钟线与LCD相连,每发出一次CLK(高低电平),电子枪就移动一个像素。

颜色如何确定?



  • 由连接LCD的三组线RGB三原色混合而成:R(Red)、G(Green)、B(Blue)确定。

电子枪如何得知应跳到下一行?



  • 有一条HSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到下一行,该信号叫做行同步信号。

电子枪如何得知应跳到原点?



  • 有一条VSYNC信号线与LCD相连,每发出一次脉冲(高低电平),电子枪就跳到原点,该信号叫做帧同步信号。

RGB线上的数据从何而来?



  • 内存里面划分一块显存(framebuffer),里面存放了要显示的数据,LCD控制器从里面将数据读出来,通过RGB三组线传给电子枪,电子枪再依次打到显示屏上。

前面的信号由谁发给LCD?



  • 有S3C2440里面的LCD控制器来控制发出信号。

工作原理:



  • LCD屏可以看作是由许多象素构成的,比如320*240就是由320*240个象素构成的,每个象素由RGB三色调和,每种颜色又由多个位组成。比如我们的开发板上的LCD,有320*240个象素,每个象素由RGB三色调和,RGB三色位数分别为:565。

  • S3C2440内集成了LCD控制器,LCD控制器外接LCD,每来一个VLCK,就会从左到右在LCD屏幕上显示一个象素的颜色,而这一个个象素的颜色就存放在显存里,在嵌入式领域,一般不会佩戴专门的显存,而是从内存SDRAM中划分出一部分充当显存;

  • HSYNC引脚每发出一个脉冲,表示一行的数据开始发送;

  • VSYNC引脚每发出一个冒充,表示一帧的数据开始发送。


1.2  frambuffer设备

我们在Mini2440裸机开发之LCD编程(GB2312、ASCII字库制作) 中介绍了如何在LCD显示屏中显示一张图片,其核心步骤就是向framebuffer中写入图片数据。

在linux中,如果我们的系统想使用GUI(图形界面接口),这时LCD设备驱动程序就应该编写成frambuffer接口,而不是像裸机中那样只编写操作底层的LCD控制器接口。

framebuffer是linux系统为显示设备提供的一个用户接口,它将显示缓冲区抽象,屏蔽图像硬件的底层差异,允许上层应用程序在图形模式下直接对显示缓冲区进行操作,用户应用程序可以通过framebuffer透明地访问不同类型的显示设备。

linux抽象出framebuffer这个帧缓冲区可以供用户应用程序直接读写,通过更改framebuffer中的内容,就可以立刻显示在LCD显示屏上。

framebuffer是一个标准的字符设备,主设备号是29,次设备号根据缓冲区的数目而定。framebuffer对应/dev/fb%d设备文件。

对用户程序而言,framebuffer设备它和/dev下面的其它设备没有什么区别,用户可以把frameBuffer看成一块内存,既可以写,又可以读。显示器将根据内存数据显示对应的图像界面,这一切都由framebuffer设备驱动来完成。


二、framebuffer设备驱动框架图

framebuffer设备驱动在linux系统框架如下图:


三、基础数据结构


3.1 fb_info结构体

struct fb_info定义在include/linux/fb.h文件中,用于保存我们framebuffer设备信息,其内部提供了对framebuffer设备操作的函数指针:

 

struct fb_info {
atomic_t count;
int node;
int flags;
/*
* -1 by default, set to a FB_ROTATE_* value by the driver, if it knows
* a lcd is not mounted upright and fbcon should rotate to compensate.
*/
int fbcon_rotate_hint;
struct mutex lock; /* Lock for open/release/ioctl funcs */
struct mutex mm_lock; /* Lock for fb_mmap and smem_* fields */
struct fb_var_screeninfo var; /* Current var */
struct fb_fix_screeninfo fix; /* Current fix */
struct fb_monspecs monspecs; /* Current Monitor specs */
struct work_struct queue; /* Framebuffer event queue */
struct fb_pixmap pixmap; /* Image hardware mapper */
struct fb_pixmap sprite; /* Cursor hardware mapper */
struct fb_cmap cmap; /* Current cmap */
struct list_head modelist; /* mode list */
struct fb_videomode *mode; /* current mode */
#if IS_ENABLED(CONFIG_FB_BACKLIGHT)
/* 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
#ifdef CONFIG_FB_DEFERRED_IO
struct delayed_work deferred_work;
struct fb_deferred_io *fbdefio;
#endif
struct fb_ops *fbops;
struct device *device; /* This is the parent */
struct device *dev; /* This is this fb device */
int class_flag; /* private sysfs flags */
#ifdef CONFIG_FB_TILEBLITTING
struct fb_tile_ops *tileops; /* Tile Blitting */
#endif
union {
char __iomem *screen_base; /* Virtual address */
char *screen_buffer;
};
unsigned
long screen_size; /* Amount of ioremapped VRAM or 0 */
void *pseudo_palette; /* Fake palette of 16 colors */
#define FBINFO_STATE_RUNNING 0
#define FBINFO_STATE_SUSPENDED 1
u32 state;
/* Hardware state i.e suspend */
void *fbcon_par; /* fbcon use-only private area */
/* From here on everything is device dependent */
void *par;
/* we need the PCI or similar aperture base/size not
smem_start/size as smem_start may just be an object
allocated inside the aperture so may not actually overlap
*/
struct apertures_struct {
unsigned
int count;
struct aperture {
resource_size_t
base;
resource_size_t size;
} ranges[
0];
}
*apertures;
bool skip_vt_switch; /* no VT switch on suspend/resume required */
};

部分参数含义如下:



  • count:fb_info的引用计数,fb_open时使其+1,release时使其-1,为0时销毁;

  • node:全局变量registered_fb中的索引值,注册的时候分配,通过node可以索引fb_info;

  • flags:一些标志位,有关于硬件加速的,大小端,fb的内存位置(设备或者内存),具体硬件加速的方法,表明哪个使用了硬件加速;

  • var:描述的是具体屏的一些参数,包括可见的分辨率,Bpp(bits_per_pixel),还有具体的时钟信号,包括bp,fp,vsync,hsync等,可以通过应用层设置也可以驱动层配置,相关设置时序的工具有fbset,还有相关的一些调色板配置;

  • fix:描述的是不可变量,驱动中控制参数,不能在用户层更改。包括显存起始位置(一般是显示控制器DMA起始地址-物理地址,smem_start),framebuffer的长度(smem_len);

  • monspecs:描述的是显示器的一些参数,时序,生产日期等,一般这种信息描述在显示器中的EDID中,通过解析EDID来填充此参数;

  • queue:事件队列,不过分析多个驱动,并没有发现使用该字段的,等遇到再做更新;

  • pixmap,sprite(光标)都是像素图,注册framebuffer的时候会默认申请;

  • cmap:设备独立的 colormap 信息,可以通过 ioctl 的 FBIOGETCMAP 和 FBIOPUTCMAP 命令设置 colormap;

  • modelist:将var参数转化成video mode,然后存入这个链表;

  • mode:一些时序,刷新率扫描方式(vmode)(隔行,逐行),极性(sync);

  • 关于背光CONFIG_FB_BACKLIGHT,有关于背光曲线以及背光设备注册,需要注意的是需要在注册framebuffer之前就对其初始化;

  • CONFIG_FB_DEFERRED_IO,延迟IO,使用缺页中断的原理操作,减少FBIOPAN_DISPLAY带来的系统调用开支。

  • fbops:提供具体的fb操作函数,主要是通过fbmem.c中提供的文件操作函数,间接调用fb_ops,主要的操作有fb_check_var,fb_pan_display,fb_mmap,等,以下三个函数提供了绘图的操作,可以使用系统中的绘图函数,也可以重写硬件加速的绘图函数;

  • device:fb_info的设备父节点,对应即sys/device/xxx/fb_info;

  • dev:设备指针,注册framebuffer时创建;

  • pseudo_palette:伪调色板;

  • state:硬件状态,在fbmem中会设置成suspend以及resume;

  • skip_vt_switch:关于VT switch,是与console切换以及PM相关的;


3.2 fb_info标志位

fb_info标志位定义如下:

/* FBINFO_* = fb_info.flags bit flags */
#define FBINFO_DEFAULT 0
#define FBINFO_HWACCEL_DISABLED 0x0002
/* When FBINFO_HWACCEL_DISABLED is set:
* Hardware acceleration is turned off. Software implementations
* of required functions (copyarea(), fillrect(), and imageblit())
* takes over; acceleration engine should be in a quiescent state
*/
/* hints */
#define FBINFO_VIRTFB 0x0004 /* FB is System RAM, not device. */
#define FBINFO_PARTIAL_PAN_OK 0x0040 /* otw use pan only for double-buffering */
#define FBINFO_READS_FAST 0x0080 /* soft-copy faster than rendering */
/* hardware supported ops */
/* semantics: when a bit is set, it indicates that the operation is
* accelerated by hardware.
* required functions will still work even if the bit is not set.
* optional functions may not even exist if the flag bit is not set.
*/
#define FBINFO_HWACCEL_NONE 0x0000
#define FBINFO_HWACCEL_COPYAREA 0x0100 /* required */
#define FBINFO_HWACCEL_FILLRECT 0x0200 /* required */
#define FBINFO_HWACCEL_IMAGEBLIT 0x0400 /* required */
#define FBINFO_HWACCEL_ROTATE 0x0800 /* optional */
#define FBINFO_HWACCEL_XPAN 0x1000 /* optional */
#define FBINFO_HWACCEL_YPAN 0x2000 /* optional */
#define FBINFO_HWACCEL_YWRAP 0x4000 /* optional */
#define FBINFO_MISC_USEREVENT 0x10000 /* event request
from userspace */
#define FBINFO_MISC_TILEBLITTING 0x20000 /* use tile blitting */
/* A driver may set this flag to indicate that it does want a set_par to be
* called every time when fbcon_switch is executed. The advantage is that with
* this flag set you can really be sure that set_par is always called before
* any of the functions dependent on the correct hardware state or altering
* that state, even if you are using some broken X releases. The disadvantage
* is that it introduces unwanted delays to every console switch if set_par
* is slow. It is a good idea to try this flag in the drivers initialization
* code whenever there is a bug report related to switching between X and the
* framebuffer console.
*/
#define FBINFO_MISC_ALWAYS_SETPAR 0x40000
/* where the fb is a firmware driver, and can be replaced with a proper one */
#define FBINFO_MISC_FIRMWARE 0x80000
/*
* Host and GPU endianness differ.
*/
#define FBINFO_FOREIGN_ENDIAN 0x100000
/*
* Big endian math. This is the same flags as above, but with different
* meaning, it is set by the fb subsystem depending FOREIGN_ENDIAN flag
* and host endianness. Drivers should not use this flag.
*/
#define FBINFO_BE_MATH 0x100000
/*
* Hide smem_start in the FBIOGET_FSCREENINFO IOCTL. This is used by modern DRM
* drivers to stop userspace from trying to share buffers behind the kernel's
* back. Instead dma-buf based buffer sharing should be used.
*/
#define FBINFO_HIDE_SMEM_START 0x200000

3.3 fb_ops 

fb_ops里存放时的framebuffer设备操作函数:

/*
* Frame buffer operations
*
* LOCKING NOTE: those functions must _ALL_ be called with the console
* semaphore held, this is the only suitable locking mechanism we have
* in 2.6. Some may be called at interrupt time at this point though.
*
* The exception to this is the debug related hooks. Putting the fb
* into a debug state (e.g. flipping to the kernel console) and restoring
* it must be done in a lock-free manner, so low level drivers should
* keep track of the initial console (if applicable) and may need to
* perform direct, unlocked hardware writes in these hooks.
*/
struct fb_ops {
/* open/release and usage marking */
struct module *owner;
int (*fb_open)(struct fb_info *info, int user);
int (*fb_release)(struct fb_info *info, int user);
/* For framebuffers with strange non linear layouts or that do not
* work with normal memory mapped access
*/
ssize_t (
*fb_read)(struct fb_info *info, char __user *buf,
size_t count, loff_t
*ppos);
ssize_t (
*fb_write)(struct fb_info *info, const char __user *buf,
size_t count, loff_t
*ppos);
/* checks var and eventually tweaks it to something supported,
* DO NOT MODIFY PAR
*/
int (*fb_check_var)(struct fb_var_screeninfo *var, struct fb_info *info);
/* set the video mode according to info->var */
int (*fb_set_par)(struct fb_info *info);
/* set color register */
int (*fb_setcolreg)(unsigned regno, unsigned red, unsigned green,
unsigned blue, unsigned transp,
struct fb_info *info);
/* set color registers in batch */
int (*fb_setcmap)(struct fb_cmap *cmap, struct fb_info *info);
/* blank display */
int (*fb_blank)(int blank, struct fb_info *info);
/* pan display */
int (*fb_pan_display)(struct fb_var_screeninfo *var, struct fb_info *info);
/* Draws a rectangle */
void (*fb_fillrect) (struct fb_info *info, const struct fb_fillrect *rect);
/* Copy data from area to another */
void (*fb_copyarea) (struct fb_info *info, const struct fb_copyarea *region);
/* Draws a image to the display */
void (*fb_imageblit) (struct fb_info *info, const struct fb_image *image);
/* Draws cursor */
int (*fb_cursor) (struct fb_info *info, struct fb_cursor *cursor);
/* wait for blit idle, optional */
int (*fb_sync)(struct fb_info *info);
/* perform fb specific ioctl (optional) */
int (*fb_ioctl)(struct fb_info *info, unsigned int cmd,
unsigned
long arg);
/* Handle 32bit compat ioctl (optional) */
int (*fb_compat_ioctl)(struct fb_info *info, unsigned cmd,
unsigned
long arg);
/* perform fb specific mmap */
int (*fb_mmap)(struct fb_info *info, struct vm_area_struct *vma);
/* get capability given var */
void (*fb_get_caps)(struct fb_info *info, struct fb_blit_caps *caps,
struct fb_var_screeninfo *var);
/* teardown any resources to do with this framebuffer */
void (*fb_destroy)(struct fb_info *info);
/* called at KDB enter and leave time to prepare the console */
int (*fb_debug_enter)(struct fb_info *info);
int (*fb_debug_leave)(struct fb_info *info);
};

三、fbmem.c源码分析

fbmem.c是framebuffer设备驱动的核心,它向上给应用程序提供了系统调用的接口,向下对特定的硬件提供了底层的驱动接口,底层驱动可以通过接口向内核注册自己。

fbmem.c位于drivers/video/fbdev/core路径下。我们可以在该文件定位到驱动模块的入口和出口:

module_init(fbmem_init);
module_exit(fbmem_exit);

3.1 入口函数

我们定位到fbmem.c的入口函数,也就是fbmem_init:

/**
* fbmem_init - init frame buffer subsystem
*
* Initialize the frame buffer subsystem.
*
* NOTE: This function is _only_ to be called by drivers/char/mem.c.
*
*/
static int __init
fbmem_init(
void)
{
int ret;
if (!proc_create_seq("fb", 0, NULL, &proc_fb_seq_ops))
return -ENOMEM;
ret
= register_chrdev(FB_MAJOR, "fb", &fb_fops);
if (ret) {
printk(
"unable to get major %d for fb devs\n", FB_MAJOR);
goto err_chrdev;
}
fb_class
= class_create(THIS_MODULE, "graphics");
if (IS_ERR(fb_class)) {
ret
= PTR_ERR(fb_class);
pr_warn(
"Unable to create fb class; errno = %d\n", ret);
fb_class
= NULL;
goto err_class;
}
fb_console_init();
return 0;
err_class:
unregister_chrdev(FB_MAJOR,
"fb");
err_chrdev:
remove_proc_entry(
"fb", NULL);
return ret;
}

简要分析一下该函数执行流程:



  • 创建/proc/fb文件;



  • 创建字符设备fb,主设备编号为FB_MAJOR(29),注册file_operations结构体fb_fops;



  • 调用class_create在/sys/class目录下创建graphics这个类,但是此时并没有调用device_create在/dev下创建设备节点 ;

可以通过如下命令查看字符设备:

root@zhengyang:/work/sambashare/linux-5.2.8# cat /proc/devices
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
5 ttyprintk
6 lp
7 vcs
10 misc
13 input
14 sound/midi
14 sound/dmmidi
21 sg
29 fb // 这个名字来自register_chrdev函数第二个参数
89 i2c

可以看到,确实是创建了主设备号为29的"fb"设备,而这里还没有创建设备节点,后面会提到,内核将该工作放到注册lcd驱动的接口函数里了。


3.2 fb_fops

我们再来看看file_operations结构体fb_fops:

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,
#if defined(HAVE_ARCH_FB_UNMAPPED_AREA) || \
(defined(CONFIG_FB_PROVIDE_GET_FB_UNMAPPED_AREA)
&& \
!defined(CONFIG_MMU))
.get_unmapped_area
= get_fb_unmapped_area,
#endif
#ifdef CONFIG_FB_DEFERRED_IO
.fsync
= fb_deferred_io_fsync,
#endif
.llseek
= default_llseek,
};

下面我们来一一分析这些成员函数。

3.3 fb_open

static int
fb_open(
struct inode *inode, struct file *file)
__acquires(
&info->lock)
__releases(
&info->lock)
{
int fbidx = iminor(inode); // 获取设备节点的次设备号
struct fb_info *info; // 定义fb_info指针
int res = 0;
info
= get_fb_info(fbidx); // 根据次设备编号获取lcd驱动信息
if (!info) {
request_module(
"fb%d", fbidx);
info
= get_fb_info(fbidx);
if (!info)
return -ENODEV;
}
if (IS_ERR(info))
return PTR_ERR(info);
mutex_lock(
&info->lock); // 获取互斥锁
if (!try_module_get(info->fbops->owner)) {
res
= -ENODEV;
goto out;
}
file
->private_data = info;
if (info->fbops->fb_open) {
res
= info->fbops->fb_open(info,1);
if (res)
module_put(info
->fbops->owner);
}
#ifdef CONFIG_FB_DEFERRED_IO
if (info->fbdefio)
fb_deferred_io_open(info, inode, file);
#endif
out:
mutex_unlock(
&info->lock); // 释放互斥锁
if (res)
put_fb_info(info);
return res;
}

这里我们来看一下get_fb_info函数的实现:

static struct fb_info *get_fb_info(unsigned int idx)
{
struct fb_info *fb_info;
if (idx >= FB_MAX)
return ERR_PTR(-ENODEV);
mutex_lock(
&registration_lock);
fb_info
= registered_fb[idx];
if (fb_info)
atomic_inc(
&fb_info->count);
mutex_unlock(
&registration_lock);
return fb_info;
}

可以看到get_fb_info函数将registered_fb数组的第idx个元素赋值给了fb_info,registered_fb是一个struct fb_info结构类型的全局数组:

struct fb_info *registered_fb[FB_MAX] __read_mostly;

这和数组会在register_framebuffer函数中赋值。

经过分析,我们最终会发现fb_open执行的是fb的操作函数中的fbopen函数。

3.4 fb_read

static ssize_t
fb_read(
struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned
long p = *ppos;
struct fb_info *info = file_fb_info(file);
u8
*buffer, *dst;
u8 __iomem
*src;
int c, cnt = 0, err = 0;
unsigned
long total_size;
if (!info || ! info->screen_base)
return -ENODEV;
if (info->state != FBINFO_STATE_RUNNING)
return -EPERM;
if (info->fbops->fb_read)
return info->fbops->fb_read(info, buf, count, ppos);
total_size
= info->screen_size;
if (total_size == 0)
total_size
= info->fix.smem_len;
if (p >= total_size)
return 0;
if (count >= total_size)
count
= total_size;
if (count + p > total_size)
count
= total_size - p;
buffer
= kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
return -ENOMEM;
src
= (u8 __iomem *) (info->screen_base + p);
if (info->fbops->fb_sync)
info
->fbops->fb_sync(info);
while (count) {
c
= (count > PAGE_SIZE) ? PAGE_SIZE : count;
dst
= buffer;
fb_memcpy_fromfb(dst, src, c);
dst
+= c;
src
+= c;
if (copy_to_user(buf, buffer, c)) {
err
= -EFAULT;
break;
}
*ppos += c;
buf
+= c;
cnt
+= c;
count
-= c;
}
kfree(buffer);
return (err) ? err : cnt;
}

3.5 fb_write

static ssize_t
fb_write(
struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
unsigned
long p = *ppos;
struct fb_info *info = file_fb_info(file);
u8
*buffer, *src;
u8 __iomem
*dst;
int c, cnt = 0, err = 0;
unsigned
long total_size;
if (!info || !info->screen_base)
return -ENODEV;
if (info->state != FBINFO_STATE_RUNNING)
return -EPERM;
if (info->fbops->fb_write)
return info->fbops->fb_write(info, buf, count, ppos);
total_size
= info->screen_size;
if (total_size == 0)
total_size
= info->fix.smem_len;
if (p > total_size)
return -EFBIG;
if (count > total_size) {
err
= -EFBIG;
count
= total_size;
}
if (count + p > total_size) {
if (!err)
err
= -ENOSPC;
count
= total_size - p;
}
buffer
= kmalloc((count > PAGE_SIZE) ? PAGE_SIZE : count,
GFP_KERNEL);
if (!buffer)
return -ENOMEM;
dst
= (u8 __iomem *) (info->screen_base + p);
if (info->fbops->fb_sync)
info
->fbops->fb_sync(info);
while (count) {
c
= (count > PAGE_SIZE) ? PAGE_SIZE : count;
src
= buffer;
if (copy_from_user(src, buf, c)) {
err
= -EFAULT;
break;
}
fb_memcpy_tofb(dst, src, c);
dst
+= c;
src
+= c;
*ppos += c;
buf
+= c;
cnt
+= c;
count
-= c;
}
kfree(buffer);
return (cnt) ? cnt : err;
}

3.6 fb_ioctl

参考文章

[1]十二、Linux驱动之LCD驱动

[2]15.linux-LCD层次分析(详解)

[3]Linux LCD Frambuffer 基础介绍和使用(1)

[4]Linux驱动开发 (framebuffer驱动)

[5]Linux-FrameBuffer fb_info结构体解析申请以及注册



推荐阅读
  • 在Docker中,将主机目录挂载到容器中作为volume使用时,常常会遇到文件权限问题。这是因为容器内外的UID不同所导致的。本文介绍了解决这个问题的方法,包括使用gosu和suexec工具以及在Dockerfile中配置volume的权限。通过这些方法,可以避免在使用Docker时出现无写权限的情况。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • 本文介绍了在Mac上搭建php环境后无法使用localhost连接mysql的问题,并通过将localhost替换为127.0.0.1或本机IP解决了该问题。文章解释了localhost和127.0.0.1的区别,指出了使用socket方式连接导致连接失败的原因。此外,还提供了相关链接供读者深入了解。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Linux磁盘的分区、格式化的观察和操作步骤
    本文介绍了如何观察Linux磁盘的分区状态,使用lsblk命令列出系统上的所有磁盘列表,并解释了列表中各个字段的含义。同时,还介绍了使用parted命令列出磁盘的分区表类型和分区信息的方法。在进行磁盘分区操作时,根据分区表类型选择使用fdisk或gdisk命令,并提供了具体的分区步骤。通过本文,读者可以了解到Linux磁盘分区和格式化的基本知识和操作步骤。 ... [详细]
author-avatar
e我爱你很多
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有