linux内核部件分析(四)——更强的链表klist

     前面我们说到过list_head,这是linux中通用的链表形式,双向循环链表,功能强大,实现简单优雅。可如果您认为list_head就是链表的极致,应该在linux链表界一统天下,那可就错了。据我所知,linux内核代码中至少还有两种链表能占有一席之地。一种就是hlist,一种就是本节要介绍的klist。虽然三者不同,但hlist和klist都可以看成是从list_head中发展出来的,用于特殊的链表使用情景。hlist是用于哈希表中。众所周知,哈希表主要就是一个哈希数组,为了解决映射冲突的问题,常常把哈希数组的每一项做成一个链表,这样有多少重复的都可以链进去。但哈希数组的项很多,list_head的话每个链表头都需要两个指针的空间,在稀疏的哈希表中实在是一种浪费,于是就发明了hlist。hlist有两大特点,一是它的链表头只需要一个指针,二是它的每一项都可以找到自己的前一节点,也就是说它不再循环,但仍是双向。令人不解的是,hlist的实现太绕了,比如它明明可以直接指向前一节点,却偏偏指向指针地址,还是前一节点中指向后一节点的指针地址。即使这种设计在实现时占便宜,但它理解上带来的不便已经远远超过实现上带来的小小便利。

    同hlist一样,klist也是为了适应某类特殊情形的要求。考虑一个被简化的情形,假设一些设备被链接在设备链表中,一个线程命令卸载某设备,即将其从设备链表中删除,但这时该设备正在使用中,这时就出现了冲突。当前可以设置临界区并加锁,但因为使用一个设备而锁住整个设备链表显然是不对的;又或者可以从设备本身做文章,让线程阻塞,这当然也可以。但我们上节了解了kref,就该知道linux对待这种情况的风格,给它一个引用计数kref,等计数为零就删除。klist就是这么干的,它把kref直接保存在了链表节点上。之前说到有线程要求删除设备,之前的使用仍存在,所以不能实际删除,但不应该有新的应用访问到该设备。klist就提供了一种让节点在链表上隐身的方法。下面还是来看实际代码吧。

    klist的头文件是include/linux/klist.h,实现在lib/klist.c。

struct klist_node;
struct klist {
	spinlock_t		k_lock;
	struct list_head	k_list;
	void			(*get)(struct klist_node *);
	void			(*put)(struct klist_node *);
} __attribute__ ((aligned (4)));

#define KLIST_INIT(_name, _get, _put)					\
	{ .k_lock	= __SPIN_LOCK_UNLOCKED(_name.k_lock),		\
	  .k_list	= LIST_HEAD_INIT(_name.k_list),			\
	  .get		= _get,						\
	  .put		= _put, }

#define DEFINE_KLIST(_name, _get, _put)					\
	struct klist _name = KLIST_INIT(_name, _get, _put)

extern void klist_init(struct klist *k, void (*get)(struct klist_node *),
		       void (*put)(struct klist_node *));

struct klist_node {
	void			*n_klist;	/* never access directly */
	struct list_head	n_node;
	struct kref		n_ref;
};

可以看到,klist的链表头是struct klist结构,链表节点是struct klist_node结构。先看struct klist,除了包含链表需要的k_list,还有用于加锁的k_lock。剩余的get()和put()函数是用于struct klist_node嵌入在更大的结构中,这样在节点初始时调用get(),在节点删除时调用put(),以表示链表中存在对结构的引用。再看struct klist_node,除了链表需要的n_node,还有一个引用计数n_ref。还有一个比较特殊的指针n_klist,n_klist是指向链表头struct klist的,但它的第0位用来表示是否该节点已被请求删除,如果已被请求删除则在链表循环时是看不到这一节点的,循环函数将其略过。现在你明白为什么非要在struct klist的定义后加上__attribute__((aligned(4)))。不过说实话这样在x86下仍然不太保险,但linux选择了相信gcc,毕竟是多年的战友和兄弟了,相互知根知底。

看过这两个结构,想必大

  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
要将Linux2配置为KDC服务器并负责Linux3和Linux4的验证,需要执行以下步骤: 1. 安装Kerberos软件包 在Linux2上安装Kerberos软件包,包括krb5-server和krb5-workstation。在终端中运行以下命令: ``` sudo yum install krb5-server krb5-workstation ``` 2. 配置Kerberos 编辑krb5.conf文件,该文件包含Kerberos配置信息。在终端中运行以下命令: ``` sudo vi /etc/krb5.conf ``` 添加以下内容: ``` [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = EXAMPLE.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [realms] EXAMPLE.COM = { kdc = linux2.example.com admin_server = linux2.example.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM ``` 其中,EXAMPLE.COM应替换为您的域名,linux2.example.com应替换为Linux2的主机名。 3. 创建Kerberos数据库 使用kdb5_util工具创建Kerberos数据库。在终端中运行以下命令: ``` sudo kdb5_util create -s ``` 4. 启动Kerberos服务 启动Kerberos服务,将其配置为在系统启动时自动启动。在终端中运行以下命令: ``` sudo systemctl start krb5kdc sudo systemctl enable krb5kdc sudo systemctl start kadmin sudo systemctl enable kadmin ``` 5. 创建Kerberos用户和主体 使用kadmin.local工具创建Kerberos用户和主体。在终端中运行以下命令: ``` sudo kadmin.local ``` 在kadmin.local命令行中,执行以下命令: ``` addprinc username ``` 其中,username应替换为您要创建的用户名。 6. 在Linux3和Linux4上配置Kerberos 在Linux3和Linux4上安装krb5-workstation软件包。编辑krb5.conf文件,添加以下内容: ``` [logging] default = FILE:/var/log/krb5libs.log kdc = FILE:/var/log/krb5kdc.log admin_server = FILE:/var/log/kadmind.log [libdefaults] default_realm = EXAMPLE.COM dns_lookup_realm = false dns_lookup_kdc = false ticket_lifetime = 24h renew_lifetime = 7d forwardable = true [realms] EXAMPLE.COM = { kdc = linux2.example.com admin_server = linux2.example.com } [domain_realm] .example.com = EXAMPLE.COM example.com = EXAMPLE.COM ``` 其中,EXAMPLE.COM应替换为您的域名,linux2.example.com应替换为Linux2的主机名。 7. 验证Kerberos 在Linux3或Linux4上,使用kinit命令获取Kerberos票据。在终端中运行以下命令: ``` kinit username ``` 其中,username应替换为您在Linux2上创建的用户名。 然后,可以使用klist命令查看票据信息。在终端中运行以下命令: ``` klist ``` 如果一切正常,将显示有关票据的信息。 以上是将Linux2配置为KDC服务器并负责Linux3和Linux4的验证的步骤。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值