Linux内核4.14版本——ccf时钟子系统(3)——ccf一些核心结构体

news2024/12/1 13:43:01

目录

1. struct clk_hw

2. struct clk_ops

3. struct clk_core

4. struct clk_notifier

5. struct clk

6. struct clk_gate

7. struct clk_divider

8. struct clk_mux

9. struct clk_fixed_factor

10. struct clk_fractional_divider

11. struct clk_multiplier

12. struct clk_composite

13.各结构体之间的关系

1. struct clk_hw

        从前文中我们知道,ccf根据不同时钟的特点,clock framework 将 clock 分为 Fixed rategateDividerMuxFixed factorcomposite六类,Linux 内核将上面六类设备特点抽象出来,用struct clk_hw表示。

        clock framework使用struct clk结构抽象clock,但该结构对clock consumer是透明的(不需要知道它的内部细节)。同样,struct clk对clock provider也是透明的。framework提供了struct clk_hw结构,从clock provider的角度,描述clock,该结构的定义如下:

/**
 * struct clk_hw - handle for traversing from a struct clk to its corresponding
 * hardware-specific structure.  struct clk_hw should be declared within struct
 * clk_foo and then referenced by the struct clk instance that uses struct
 * clk_foo's clk_ops
 *
 * @core: pointer to the struct clk_core instance that points back to this
 * struct clk_hw instance
 *
 * @clk: pointer to the per-user struct clk instance that can be used to call
 * into the clk API
 *
 * @init: pointer to struct clk_init_data that contains the init data shared
 * with the common clock framework.
 */
struct clk_hw {
    //指向CCF模块中对应 clock device 实例
	struct clk_core *core;
    //clk是访问clk_core的实例 每当consumer通过clk_get对CCF中的clock device(也就是clk_core) 
    //发起访问的时候都需要获取一个句柄,也就是clk
	struct clk *clk;
    //clock provider driver初始化时的数据,数据被用来初始化clk_hw对应的clk_core数据结构
	const struct clk_init_data *init;
};

/**
 * struct clk_init_data - holds init data that's common to all clocks and is
 * shared between the clock provider and the common clock framework.
 *
 * @name: clock name
 * @ops: operations this clock supports
 * @parent_names: array of string names for all possible parents
 * @num_parents: number of possible parents
 * @flags: framework-level hints and quirks
 */
struct clk_init_data {
    //该clock设备的名字
	const char		*name;
    //clock provider driver 进行的具体的 HW 操作
	const struct clk_ops	*ops;
    //描述该clk_hw的拓扑结构
	const char		* const *parent_names;
	u8			num_parents;
	unsigned long		flags;
};

        以Fixed rate clock和gate clock为例,它就包含一个 struct clk_hw 结构作为核心:

struct clk_fixed_rate {
	// 包含的 clk_hw 结构
	struct		clk_hw hw;
	unsigned long	fixed_rate;
	unsigned long	fixed_accuracy;
	u8		flags;
};

struct clk_gate {
	struct clk_hw hw;
	void __iomem	*reg;
	u8		bit_idx;
	u8		flags;
	spinlock_t	*lock;
};

由此可以知道:
        (1)每次注册进入内核的clock device设备,都会包含一个struct clk_hw结构
        (2)strutc clk_hw包含一个重要的结构体成员const struct clk_init_data *init,里面包含了注册进入内核的时钟的具体操作方法,struct clk_init_data 包含一个重要成员clk_ops,里面就是时钟设备的具体操作方法函数。

2. struct clk_ops

/**
 * struct clk_ops -  Callback operations for hardware clocks; these are to
 * be provided by the clock implementation, and will be called by drivers
 * through the clk_* api.
 *
 * @prepare:	Prepare the clock for enabling. This must not return until
 *		the clock is fully prepared, and it's safe to call clk_enable.
 *		This callback is intended to allow clock implementations to
 *		do any initialisation that may sleep. Called with
 *		prepare_lock held.
 *
 * @unprepare:	Release the clock from its prepared state. This will typically
 *		undo any work done in the @prepare callback. Called with
 *		prepare_lock held.
 *
 * @is_prepared: Queries the hardware to determine if the clock is prepared.
 *		This function is allowed to sleep. Optional, if this op is not
 *		set then the prepare count will be used.
 *
 * @unprepare_unused: Unprepare the clock atomically.  Only called from
 *		clk_disable_unused for prepare clocks with special needs.
 *		Called with prepare mutex held. This function may sleep.
 *
 * @enable:	Enable the clock atomically. This must not return until the
 *		clock is generating a valid clock signal, usable by consumer
 *		devices. Called with enable_lock held. This function must not
 *		sleep.
 *
 * @disable:	Disable the clock atomically. Called with enable_lock held.
 *		This function must not sleep.
 *
 * @is_enabled:	Queries the hardware to determine if the clock is enabled.
 *		This function must not sleep. Optional, if this op is not
 *		set then the enable count will be used.
 *
 * @disable_unused: Disable the clock atomically.  Only called from
 *		clk_disable_unused for gate clocks with special needs.
 *		Called with enable_lock held.  This function must not
 *		sleep.
 *
 * @recalc_rate	Recalculate the rate of this clock, by querying hardware. The
 *		parent rate is an input parameter.  It is up to the caller to
 *		ensure that the prepare_mutex is held across this call.
 *		Returns the calculated rate.  Optional, but recommended - if
 *		this op is not set then clock rate will be initialized to 0.
 *
 * @round_rate:	Given a target rate as input, returns the closest rate actually
 *		supported by the clock. The parent rate is an input/output
 *		parameter.
 *
 * @determine_rate: Given a target rate as input, returns the closest rate
 *		actually supported by the clock, and optionally the parent clock
 *		that should be used to provide the clock rate.
 *
 * @set_parent:	Change the input source of this clock; for clocks with multiple
 *		possible parents specify a new parent by passing in the index
 *		as a u8 corresponding to the parent in either the .parent_names
 *		or .parents arrays.  This function in affect translates an
 *		array index into the value programmed into the hardware.
 *		Returns 0 on success, -EERROR otherwise.
 *
 * @get_parent:	Queries the hardware to determine the parent of a clock.  The
 *		return value is a u8 which specifies the index corresponding to
 *		the parent clock.  This index can be applied to either the
 *		.parent_names or .parents arrays.  In short, this function
 *		translates the parent value read from hardware into an array
 *		index.  Currently only called when the clock is initialized by
 *		__clk_init.  This callback is mandatory for clocks with
 *		multiple parents.  It is optional (and unnecessary) for clocks
 *		with 0 or 1 parents.
 *
 * @set_rate:	Change the rate of this clock. The requested rate is specified
 *		by the second argument, which should typically be the return
 *		of .round_rate call.  The third argument gives the parent rate
 *		which is likely helpful for most .set_rate implementation.
 *		Returns 0 on success, -EERROR otherwise.
 *
 * @set_rate_and_parent: Change the rate and the parent of this clock. The
 *		requested rate is specified by the second argument, which
 *		should typically be the return of .round_rate call.  The
 *		third argument gives the parent rate which is likely helpful
 *		for most .set_rate_and_parent implementation. The fourth
 *		argument gives the parent index. This callback is optional (and
 *		unnecessary) for clocks with 0 or 1 parents as well as
 *		for clocks that can tolerate switching the rate and the parent
 *		separately via calls to .set_parent and .set_rate.
 *		Returns 0 on success, -EERROR otherwise.
 *
 * @recalc_accuracy: Recalculate the accuracy of this clock. The clock accuracy
 *		is expressed in ppb (parts per billion). The parent accuracy is
 *		an input parameter.
 *		Returns the calculated accuracy.  Optional - if	this op is not
 *		set then clock accuracy will be initialized to parent accuracy
 *		or 0 (perfect clock) if clock has no parent.
 *
 * @get_phase:	Queries the hardware to get the current phase of a clock.
 *		Returned values are 0-359 degrees on success, negative
 *		error codes on failure.
 *
 * @set_phase:	Shift the phase this clock signal in degrees specified
 *		by the second argument. Valid values for degrees are
 *		0-359. Return 0 on success, otherwise -EERROR.
 *
 * @init:	Perform platform-specific initialization magic.
 *		This is not not used by any of the basic clock types.
 *		Please consider other ways of solving initialization problems
 *		before using this callback, as its use is discouraged.
 *
 * @debug_init:	Set up type-specific debugfs entries for this clock.  This
 *		is called once, after the debugfs directory entry for this
 *		clock has been created.  The dentry pointer representing that
 *		directory is provided as an argument.  Called with
 *		prepare_lock held.  Returns 0 on success, -EERROR otherwise.
 *
 *
 * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
 * implementations to split any work between atomic (enable) and sleepable
 * (prepare) contexts.  If enabling a clock requires code that might sleep,
 * this must be done in clk_prepare.  Clock enable code that will never be
 * called in a sleepable context may be implemented in clk_enable.
 *
 * Typically, drivers will call clk_prepare when a clock may be needed later
 * (eg. when a device is opened), and clk_enable when the clock is actually
 * required (eg. from an interrupt). Note that clk_prepare MUST have been
 * called before clk_enable.
 */
struct clk_ops {
	int		(*prepare)(struct clk_hw *hw);
	void		(*unprepare)(struct clk_hw *hw);
	int		(*is_prepared)(struct clk_hw *hw);
	void		(*unprepare_unused)(struct clk_hw *hw);
	int		(*enable)(struct clk_hw *hw);
	void		(*disable)(struct clk_hw *hw);
	int		(*is_enabled)(struct clk_hw *hw);
	void		(*disable_unused)(struct clk_hw *hw);
	unsigned long	(*recalc_rate)(struct clk_hw *hw,
					unsigned long parent_rate);
	long		(*round_rate)(struct clk_hw *hw, unsigned long rate,
					unsigned long *parent_rate);
	int		(*determine_rate)(struct clk_hw *hw,
					  struct clk_rate_request *req);
	int		(*set_parent)(struct clk_hw *hw, u8 index);
	u8		(*get_parent)(struct clk_hw *hw);
	int		(*set_rate)(struct clk_hw *hw, unsigned long rate,
				    unsigned long parent_rate);
	int		(*set_rate_and_parent)(struct clk_hw *hw,
				    unsigned long rate,
				    unsigned long parent_rate, u8 index);
	unsigned long	(*recalc_accuracy)(struct clk_hw *hw,
					   unsigned long parent_accuracy);
	int		(*get_phase)(struct clk_hw *hw);
	int		(*set_phase)(struct clk_hw *hw, int degrees);
	void		(*init)(struct clk_hw *hw);
	int		(*debug_init)(struct clk_hw *hw, struct dentry *dentry);
};

        is_prepared,判断clock是否已经prepared。可以不提供,clock framework core会维护一个prepare的计数(该计数在clk_prepare调用时加一,在clk_unprepare时减一),并依据该计数判断是否prepared;
        unprepare_unused,自动unprepare unused clocks;
        is_enabled,和is_prepared类似;
        disable_unused,自动disable unused clocks;
        注1:clock framework core提供一个clk_disable_unused接口,在系统初始化的late_call中调用,用于关闭unused clocks,这个接口会调用相应clock的.unprepare_unused和.disable_unused函数。
       recalc_rate,以parent clock rate为参数,从新计算并返回clock rate;

        注2:细心的读者可能会发现,该结构没有提供get_rate函数,因为会有一个rate变量缓存,另外可以使用recalc_rate。
        round_rate,该接口有点特别,在返回rounded rate的同时,会通过一个指针,返回round后parent的rate。这和CLK_SET_RATE_PARENT flag有关,后面会详细解释;
        init,clock的初始化接口,会在clock被register到内核时调用。

/*
* flags used across common struct clk.  these flags should only affect the
* top-level framework.  custom flags for dealing with hardware specifics
* belong in struct clk_foo
*/
#define CLK_SET_RATE_GATE       BIT(0) /* must be gated across rate change */
#define CLK_SET_PARENT_GATE     BIT(1) /* must be gated across re-parent */
#define CLK_SET_RATE_PARENT     BIT(2) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED       BIT(3) /* do not gate even if unused */
#define CLK_IS_ROOT             BIT(4) /* root clk, has no parent */
#define CLK_IS_BASIC            BIT(5) /* Basic clk, can't do a to_clk_foo() */
#define CLK_GET_RATE_NOCACHE    BIT(6) /* do not use the cached clk rate */

上面是framework级别的flags,可以使用或的关系,指定多个flags,解释如下:

CLK_SET_RATE_GATE,表示在改变该clock的rate时,必须gated(关闭); 
CLK_SET_PARENT_GATE,表示在改变该clock的parent时,必须gated(关闭); 
CLK_SET_RATE_PARENT,表示改变该clock的rate时,要将该改变传递到上层parent(下面再详细说明); 
CLK_IGNORE_UNUSED,忽略disable unused的调用; 
CLK_IS_ROOT,该clock为root clock,没有parent; 
CLK_IS_BASIC,不再使用了; 
CLK_GET_RATE_NOCACHE,get rate时,不要从缓存中拿,而是从新计算。

        注3:round_rate和CLK_SET_RATE_PARENT 
        当clock consumer调用clk_round_rate获取一个近似的rate时,如果该clock没有提供.round_rate函数,有两种方法: 
        1)在没有设置CLK_SET_RATE_PARENT标志时,直接返回该clock的cache rate 
        2)如果设置了CLK_SET_RATE_PARENT标志,则会询问parent,即调用clk_round_rate获取parent clock能提供的、最接近该rate的值。这是什么意思呢?也就是说,如果parent clock可以得到一个近似的rate值,那么通过改变parent clock,就能得到所需的clock。 在后续的clk_set_rate接口中,会再次使用该flag,如果置位,则会在设置rate时,传递到parent clock,因此parent clock的rate可能会重设。 讲的很拗口,我觉得我也没说清楚,那么最好的方案就是:在写clock driver时,最好不用这个flag,简单的就是最好的(前提是能满足需求)。

3. struct clk_core

/***    private data structures    ***/
struct clk_core {
	const char		*name;    //clk核心名称
	const struct clk_ops	*ops;   //该clk核心对应的ops。
	struct clk_hw		*hw;   //指向struct clk_hw类型的指针,表示这个时钟节点的硬件实现;
	struct module		*owner;
	struct clk_core		*parent;  //指向struct clk_core类型的指针,表示这个时钟节点的父时钟节点;
	const char		**parent_names;
	struct clk_core		**parents;  //一个数组,表示这个时钟节点可能的所有父时钟节点及其对应的索引;
	u8			num_parents;    //表示这个时钟节点总共有多少个可能的父时钟节点;
	u8			new_parent_index;
	unsigned long		rate;
	unsigned long		req_rate;
	unsigned long		new_rate;
	struct clk_core		*new_parent;
	struct clk_core		*new_child;
	unsigned long		flags;
	bool			orphan;
	unsigned int		enable_count;
	unsigned int		prepare_count;
	unsigned long		min_rate;
	unsigned long		max_rate;
	unsigned long		accuracy;  //表示这个时钟节点的频率精度;
	int			phase;             //表示这个时钟节点的相位;
	struct hlist_head	children;  //一个链表头,用于将所有子时钟节点组织成一个列表。
	struct hlist_node	child_node;
	struct hlist_head	clks;
	unsigned int		notifier_count;
#ifdef CONFIG_DEBUG_FS
	struct dentry		*dentry;
	struct hlist_node	debug_node;
#endif
	struct kref		ref;
};

        从上述结构的组成元素可知,struct clk_core是strcuct device的子类,因为一款SOC的时钟关系一般以“树状”进行组织,在struct clk_core中提供描述父clk_core和子clk_core的组成元素。

4. struct clk_notifier

        stuct clk_notifier用于将CLK与通知器进行关联,也就是定义clk的通知器,基于srcu实现。该结构实现如下(/linux/include/linux/clk.h):

struct clk_notifier {
 struct clk   *clk;  //与该通知器关联的clk。
 struct srcu_notifier_head notifier_head; //用于这个CLK的blocking_notifier_head通知器。
 struct list_head  node;
};

常用API:

//注册一个通知块(notifier block),以便在指定时钟发生事件(例如频率变化)时接收通知。
int clk_notifier_register(struct clk *clk, struct notifier_block *nb);

//注销一个通知块
int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb);

//带资源管理注册一个通知块(notifier block),以便在指定时钟发生事件(如频率变化)时接收通知。确保在设备驱动程序卸载时自动注销通知块。
int devm_clk_notifier_register(struct device *dev, struct clk *clk,struct notifier_block *nb);

5. struct clk

struct clk {
 struct clk_core *core;          //表示clk核心。
 struct device *dev;             //clk设备的父设备。
 const char *dev_id;             //设备id。
 const char *con_id;        
 unsigned long min_rate;         //最小频率。
 unsigned long max_rate;         //最大频率。
 unsigned int exclusive_count;   //独占计数。
 struct hlist_node clks_node;    //clk链表。
};

6. struct clk_gate

struct clk_gate {
    struct clk_hw hw;     //处理公共接口和特定于硬件的接口。
    void __iomem *reg; //寄存器控制门。
    u8  bit_idx;      //单比特控制门。
    u8  flags;        //特定硬件的falg标志。
    spinlock_t *lock;    //自旋锁。
};
clk_register_gate()/clk_unregister_gate()

7. struct clk_divider

struct clk_divider描述可调的分频时钟,该结构定义如下:

struct clk_divider {
    struct clk_hw hw;    //处理公共接口和特定硬件的接口
    void __iomem *reg;   //分频器的寄存器
    u8  shift;    //分频位域的偏移量
    u8  width;    //分频位域的宽度
    u8  flags;    //标志
    const struct clk_div_table *table; //数组的值/除数对,最后一项div = 0。
    spinlock_t *lock;   //注册锁
};

        具有影响其输出频率的可调分压器的时钟。实现.recalc_rate,.set_rate和.round_rate。

clk_register_divider()/clk_unregister_divider()
clk_hw_register_divider()/clk_hw_unregister_divider()

8. struct clk_mux

struct clk_mux用于描述多路复用器的时钟,该结构定义如下:

struct clk_mux {
 struct clk_hw hw;
 void __iomem *reg;
 const u32 *table;
 u32  mask;
 u8  shift;
 u8  flags;
 spinlock_t *lock;
};
void clk_unregister_mux(struct clk *clk);
void clk_hw_unregister_mux(struct clk_hw *hw);

9. struct clk_fixed_factor

struct clk_fixed_factor用于倍频和分频时钟。该结构定义如下:

struct clk_fixed_factor {
 struct clk_hw hw;   //处理公共接口和特定硬件的接口。
 unsigned int mult; //倍频器
 unsigned int div;  //分频器
};

10. struct clk_fractional_divider

struct clk_fractional_divider用于描述可调分数的分频时钟,该结构定义如下:

struct clk_fractional_divider {
 struct clk_hw hw;                          //处理公共接口和特定硬件的接口
 void __iomem *reg;                        //用于分频器的寄存器
 u8  mshift;                              //分频位域分子的偏移量
 u8  mwidth;                              //分频位域分子的宽度
 u8  nshift;                              //分频位域分母的偏移量
 u8  nwidth;                              //分频位域分母的宽度
 u8  flags;                               //标志位
 void  (*approximation)(struct clk_hw *hw,   //近似方法的callback
    unsigned long rate, unsigned long *parent_rate,
    unsigned long *m, unsigned long *n);    
 spinlock_t *lock;                            //注册锁
};

11. struct clk_multiplier

struct clk_multiplier结构用于描述可调的倍频时钟,该结构定义如下:

struct clk_multiplier {
 struct clk_hw hw;          //处理公共接口和特定硬件的接口
 void __iomem *reg;        //倍频器的寄存器
 u8  shift;               //乘法位域的偏移量
 u8  width;               //乘法位域的宽度
 u8  flags;               //标志
 spinlock_t *lock;           //注册锁
};

12. struct clk_composite

struct clk_composite结构用于描述多路复用器、分频器和门控时钟的组合时钟。该结构定义如下:

struct clk_composite {
 struct clk_hw hw;            //处理公共接口和特定硬件的接口
 struct clk_ops ops;           //clk对应的ops的callback

 struct clk_hw *mux_hw;       //处理复合和硬件特定多路复用时钟
 struct clk_hw *rate_hw;      //处理复合和硬件特定的频率时钟
 struct clk_hw *gate_hw;      //处理之间的组合和硬件特定的门控时钟

 const struct clk_ops *mux_ops;    //对mux的时钟ops
 const struct clk_ops *rate_ops;   //对rate的时钟ops
 const struct clk_ops *gate_ops;   //对gate的时钟ops
};

13.各结构体之间的关系

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2251139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

点云处理中obb算法原理和法向量求解方法

主要数学原理PCA PCA(Principal Component Analysis,主成分分析)是数据分析中的一种重要技术,通过它可以将高维数据投影到低维空间,找到数据的主要结构。在点云分析中,PCA 可以帮助我们提取点云数据中的主…

shell编程7,bash解释器的 for循环+while循环

声明! 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&#…

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架,支持多种机器学习任务,如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程,涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow: pip install tensorflow…

wxFormBuilder:可视化设计、学习wxWidgets自带UI控件的好工具

wxFormBuilder很快就能拼出一个界面,而且可以直接出对应的代码,拷贝到项目里小改一下就能用。

Vim操作

1. Vim的模式 2.正常模式->编辑模式 在上⽅插⼊⼀⾏: O在下⽅插⼊⼀⾏: o (open)在当前光标前插⼊: i在⾏⾸插⼊: I在当前光标后插⼊: a在⾏尾插⼊: A 3.常见命令行 1、拷贝当前行 yy ,拷贝当前行向下…

阿里云服务器(centos7.6)部署前后端分离项目(MAC环境)

Jdk17安装部署 下载地址:https://www.oracle.com/java/technologies/downloads/ 选择自己需要的jdk版本进行下载。 通过mac终端scp命令上传下载好的jdk17到服务器的/usr/local目录下 scp -r Downloads/jdk-17.0.13_linux-x64_bin.tar.gz 用户名服务器ip地址:/us…

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字,应用会判断是否接近目标数字,并提供提示“高一点”或“低一点”,直到用户猜中目标数字。这个小游戏结合状态管理和用户交互,是一个入门级的互动应用示例。 关键词 UI互…

Python系列 - MQTT协议

Python系列 - MQTT协议 资源连接 MQTT的介绍和应用场景的示例说明 一、什么是MQTT 百度关于MQTT的介绍如下: MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布订阅范式的消息协议。它工作在 TCP/IP协议之上,是为硬件性能低下的远程设…

ipad项目 蓝湖宽度

ipad项目 横屏状态时 蓝湖宽度设置930px media screen and (orientation: portrait) {/* 竖屏时的样式 */ } media screen and (orientation: landscape) {/* 默认是 横屏时的样式 */ }

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map

本博文部分参考 博客 ,强烈推荐这篇博客,写得超级全面!!! 图片来源 Java 集合框架 主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合(单列…

搭建深度学习框架+nn.Module

一、搭建项目框架(YOLO框架的简约版本) 最终成品的项目框架如下图,最终实现的效果,通过自己配置的框架函数,对模型进行定义与参数调配。同时在参数配置的过程中可选择是否进行模型初始化参数的使用。适用于YOLO框架的…

FFmpeg 简介与编译

1. ffmpeg 简介: FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec,为了保证高可移…

打latex公式可以练到像手写一样快吗?

这里分享两个Python Latex工具latexify和handcalcs。 latexify生成LaTeX 数学公式 import math import latexify @latexify.with_latex #调用latexify的装饰器 def solve(a, b, c):return (-b + math.sqrt(b**2 - 4*a*c)) / (2*a)solve 更多例子.......

【Linux】磁盘 | 文件系统 | inode

🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:青果大战linux 总有光环在陨落,总有新星在闪烁 模电好难啊&#xff…

AntFlow 0.20.0版发布,增加多数据源多租户支持,进一步助力企业信息化,SAAS化

传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大,也被企业广泛采用,然后也存着在诸如学习曲线陡峭,上手难度大,流程设计操作需要专业人员,普通人无从下手等问题。。。引入工作流引擎往往需要企业储…

Scrapy管道设置和数据保存

1.1 介绍部分: 文字提到常用的Web框架有Django和Flask,接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分: Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…

洛谷 B3626 跳跃机器人 C语言 记忆化搜索

题目: https://www.luogu.com.cn/problem/B3626 题目描述 地上有一排格子,共 n 个位置。机器猫站在第一个格子上,需要取第 n 个格子里的东西。 机器猫当然不愿意自己跑过去,所以机器猫从口袋里掏出了一个机器人!这…

docker快速部署gitlab

文章目录 场景部署步骤默认账号密码效果 场景 新增了一台机器, 在初始化本地开发环境,docker快速部署gitlab 部署步骤 编写dockerfile version: 3.7services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlabenviron…

计算机视觉工程师紧张学习中!

在当今这个日新月异的科技时代,计算机视觉作为人工智能的重要分支,正以前所未有的速度改变着我们的生活和工作方式。为了紧跟时代步伐,提升自我技能,一群怀揣梦想与热情的计算机视觉设计开发工程师们聚集在了本次线下培训活动中。…

RabbitMq死信队列(详解)

死信队列的概念 死信(dead message)简单理解就是因为种种原因,无法被消费的信息,就是死信。 有死信,自然就有死信队列。当消息在⼀个队列中变成死信之后,它能被重新被发送到另⼀个交换器中,这个交换器就是DLX( Dead L…