当前位置: 首页 > news >正文

01 C语言使用链表实现队列(Queue、FIFO)模块

01 C语言使用链表实现队列(Queue、FIFO)模块

作者将狼才鲸
创建日期2023-03-08
  • Gitee源码仓库地址:C语言使用链表实现队列(Queue、FIFO)模块

  • Linux原生的队列KFIFO一次只能操作一个队列,操作变长元素时,判断队列里元素个数不容易,在复杂场景下使用不方便;消息队列msgbuf的实现又太复杂,所以自行实现FIFO队列(queue)。


  • 运行结果:
jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/26_队列_缓存 (develop)
$ make
gcc -o demo queue_test.c queue.cjim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/26_队列_缓存 (develop)
$ make run
./demoput:
0
1
2
3
4
5
6
7get:
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/26_队列_缓存 (develop)
  • 源码展示:

  • Makefile:

default:gcc -o demo queue_test.c queue.c
run:./demo
clean:rm demo
  • queue_test.c
#include "queue.h"
#include <string.h>	/* memcpy */
#include <stdio.h>	/* printf */#define BUFFER_COUNT		8	/* 缓存总个数 */
#define BUFFER_UNIT_SIZE	32	/* 单个缓存的最大长度 *//* 单个缓存元素 */
typedef struct _queue_buf {queue_t queue;char *buf;
} queue_buf_t;static char g_buf[BUFFER_COUNT][BUFFER_UNIT_SIZE];	/* 开辟的缓存空间 */
static queue_buf_t queue_buf[BUFFER_COUNT];	/* 所有缓存节点 */int main()
{int i;queue_entry_t queue_entry;	/* 整个缓存队列的入口 */queue_entry_init(&queue_entry);	/* 初始化队列入口 *//* 初始化,将所有缓存放到已释放队列中 */for (i = 0; i < BUFFER_COUNT; i++) {queue_init(&queue_buf[i].queue);	/* 初始化每个队列元素 */queue_buf[i].buf = g_buf[i];queue_buf[i].queue.queue_entry = &queue_entry;queue_free(&queue_buf[i].queue);	/* 将所有缓存加入到已释放队列 */}/* 读取所有空闲缓存,赋值后存到已使用队列中 */i = 0;printf("\nput:\n");while (1) {queue_t *pq = queue_alloc(&queue_entry);if (!pq)break;queue_buf_t *pqbuf = container_of(pq, queue_buf_t, queue);memcpy(pqbuf->buf, &i, sizeof(int));	/* 赋值,递增序列 */printf("%d\n", i);i++;queue_put(NULL, pq, QUEUE_USED);}/* 读取所有已使用缓存,将里面内容打印出来,然后用完后重新放回已释放队列 */i = 0;printf("\nget:\n");while (1) {queue_t *pq = queue_get(&queue_entry, QUEUE_USED);if (!pq)break;queue_buf_t *pqbuf = container_of(pq, queue_buf_t, queue);printf("%d: %d\n", i, *(int *)pqbuf->buf);	/* 打印值,看是不是递增序列 */i++;queue_free(pq);}return 0;
}
  • queue.h
/******************************************************************************* \brief	队列(FIFO、Queue、缓存)的实现* \details	不能单独使用,不包含实际的缓存数据,需要和上层结构体结合在一起使用* \remarks Linux原生的队列kfifo一次只能操作一个队列,操作变长元素时,判断队列里*			元素个数不容易,在复杂场景下使用不方便;消息队列msgbuf的实现又太复杂,*			所以在这里自行实现FIFO队列(queue)模块* \author	将狼才鲸* \date	2023-03-08******************************************************************************/#ifndef _QUEUE_H_
#define _QUEUE_H_#include "list.h"
#include <stddef.h>	/* NULL */#if 0//defined(TARGET_LINUX32) || defined(TARGET_LINUX64)	\|| defined(_MSC_VER) || defined(WIN32) || defined(_WIN64)/* 如果在操作系统之中,需要上锁 */
#	include <pthread.h>typedef pthread_mutex_t queue_lock_t;
#	define queue_lock_init(lock)	pthread_mutex_init((lock), NULL)
#	define queue_lock(lock)			pthread_mutex_lock((lock))
#	define queue_unlock(lock)		pthread_mutex_unlock((lock))
#	define queue_lock_destroy(lock)	pthread_mutex_destroy((lock))
#else	/* OS *//* 如果是裸机,无需上锁 */typedef int queue_lock_t;
#	define queue_lock_init(lock)
#	define queue_lock(lock)
#	define queue_unlock(lock)
#	define queue_lock_destroy(lock)
#endif	/* OS */enum {QUEUE_USED,	/* 已使用的队列 */QUEUE_FREE,	/* 已释放的队列 */QUEUE_MEMBER_MAX
};/* 一个队列的入口 */
typedef struct _queue_entry {struct list_head lists[QUEUE_MEMBER_MAX];	/* 队列中的已使用链表和已释放链表 */queue_lock_t lock;
} queue_entry_t;/* 一个队列节点 */
typedef struct _queue {struct list_head node;	/* 队列里的一个缓存对应的节点 *//* 该节点所属的队列(因为可能会同时存在多个队列,节点也可以跨队列拷贝,所以每个队列元素自身携带队列入口) */queue_entry_t *queue_entry;
} queue_t;/*** \brief	初始化队列入口*/
extern void queue_entry_init(queue_entry_t *pqe);/*** \brief	销毁队列* \param	pqe:	queue_entry_t * 队列入口*/
#define queue_entry_destroy(pqe) queue_lock_destroy((pqe)->lock)/*** \brief	初始化一个队列中的元素*/
extern void queue_init(queue_t *pq);/*** \brief	将队列元素释放到其它队列或自己队列的已使用入口或已释放入口* \param	line:	QUEUE_USED or QUEUE_FREE*/
extern int queue_put(queue_entry_t *pqe, queue_t *pq, int line);/*** \brief	从队列入口的已使用入口或已释放入口获取一个队列元素* \param	line:	QUEUE_USED or QUEUE_FREE*/
extern queue_t *queue_get(queue_entry_t *pqe, int line);/*** \brief	从队列中申请一个可用的缓存* \param	pge:	queue_entry_t * 队列入口指针* \return	queue_t *:	获取的队列节点*/
#define queue_alloc(pqe)	queue_get((pqe), QUEUE_FREE)/*** \brief	用完后将缓存进行释放* \param	pg:	queue_t * 一个缓存节点指针* \return	错误码*/
#define queue_free(pq)	queue_put(NULL, (pq), QUEUE_FREE)/*** \brief	预览已使用或者已释放队列中的第一个元素* \details	该元素预览后不会被弹出* \param	line:	QUEUE_USED or QUEUE_FREE*/
extern queue_t *queue_peek(queue_entry_t *pqe, int line);/*** \brief	获取已使用或者已释放队列中剩余的元素个数* \param	line:	QUEUE_USED or QUEUE_FREE*/
extern int queue_count(queue_entry_t *pqe, int line);#endif /* _QUEUE_H_ */
  • queue.c
#include "queue.h"
#include "util_errno.h"/*** \brief	初始化队列入口,这时候整个队列是空的*/
void queue_entry_init(queue_entry_t *pqe)
{if (!pqe)return;queue_lock_init(&(pqe->lock));queue_lock(&(pqe->lock));for (int i = 0; i < QUEUE_MEMBER_MAX; i++) {init_list_head(&(pqe->lists[i]));}queue_unlock(&(pqe->lock));
}/*** \brief	初始化一个队列中的元素*/
void queue_init(queue_t *pq)
{if (!pq)return;init_list_head(&(pq->node));pq->queue_entry = NULL;
}/*** \brief	将队列元素释放到其它队列或自己队列的已使用入口或已释放入口* \param	line:	QUEUE_USED or QUEUE_FREE*/
int queue_put(queue_entry_t *pqe, queue_t *pq, int line)
{list_head_t *node, *head;if (!pq || line >= QUEUE_MEMBER_MAX)return -EPERM;if (!pqe)pqe = pq->queue_entry;if (!pqe)return -EPERM;queue_lock(&(pqe->lock));node = &(pq->node);			/* 当前队列节点 */head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */list_del_init(node);		/* 删除node原来的链表,并重新初始化node这个链表 */list_add_tail(node, head);	/* 加到链表尾,先入先出 */queue_unlock(&(pqe->lock));return 0;}/*** \brief	从队列入口的已使用入口或已释放入口获取一个队列元素* \param	line:	QUEUE_USED or QUEUE_FREE*/
queue_t *queue_get(queue_entry_t *pqe, int line)
{queue_t *pq;list_head_t *node, *head;if (!pqe || line >= QUEUE_MEMBER_MAX)return NULL;queue_lock(&(pqe->lock));head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */pq = NULL;if (!list_empty_careful(head)) {pq = list_first_entry(head, queue_t, node);	/* 获取队列的第一个元素 */node = &(pq->node);list_del_init(node);	/* 销毁该元素 */}queue_unlock(&(pqe->lock));return pq;
}/*** \brief	预览已使用或者已释放队列中的第一个元素* \details	该元素预览后不会被弹出* \param	line:	QUEUE_USED or QUEUE_FREE*/
queue_t *queue_peek(queue_entry_t *pqe, int line)
{queue_t *pq;list_head_t *head;if (!pqe || line >= QUEUE_MEMBER_MAX)return NULL;queue_lock(&(pqe->lock));head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */pq = NULL;if (!list_empty_careful(head)) {pq = list_first_entry(head, queue_t, node);	/* 获取队列的第一个元素 */}queue_unlock(&(pqe->lock));return pq;
}/*** \brief	获取已使用或者已释放队列中剩余的元素个数* \param	line:	QUEUE_USED or QUEUE_FREE*/
int queue_count(queue_entry_t *pqe, int line)
{int count = 0;list_head_t *node, *n, *head;if (!pqe || line >= QUEUE_MEMBER_MAX)return -EPERM;queue_lock(&(pqe->lock));head = &(pqe->lists[line]);	/* 队列中要要获取或者释放的入口 */if (!list_empty_careful(head)) {list_for_each_safe(node, n, head) {count++;}}queue_unlock(&(pqe->lock));return count;
}
  • list.h
/******************************************************************************* \brief	双向链表(不直接包含数据)* \details	约定链表入口地址本身是尾(最后弹出)地址,head->next是头(最先弹出)地址;*			链表入口地址本身是无效的节点,即使弹出所有的节点,也只弹到入口之前*			的节点为止;*			一个双向链表实际上就是一个最简单的FIFO,就一个先进先出功能* \note	File format: UTF-8,中文编码:UTF-8;*			本链表不包含具体的数据,数据须在包含本链表成员的上层结构体中进行操作,*			也就是说本链表不能单独使用,必须和上层模块联用;*			本模块当前必须在gcc中才能编译通过,在msvc中不行,要想在Windows中使用*			需要去除typeof关键字,并在参数中增加一个变量;* \remarks	基于linux_6.1-rc4\scripts\kconfig\list.h,*			该源文件是从include\linux\list.h简化而来;*			Linux kernel源码中其它可供参考的链表还有:*			linux_6.1-rc4\scripts\kconfig\list.h  最好用*			linux_6.1-rc4\tools\usb\usbip\libsrc\list.h  可用*			linux_6.1-rc4\scripts\mod\list.h  可用*			linux_6.1-rc4\tools\firewire\list.h  另一种写法*			linux_6.1-rc4\tools\include\linux\list.h  太全*			linux_6.1-rc4\include\linux\list.h  最全* \author	中文注释:将狼才鲸* \date	2023-03-05******************************************************************************/#ifndef LIST_H
#define LIST_H#include <stddef.h>	/* offsetof size_t *//*** \brief	双向链表结构体*/
typedef struct list_head {struct list_head *next, *prev;
} list_head_t;/*** \brief	定义一个链表节点并赋初值,只是简化写法* \details	这个接口一般用不到,实际使用时会用init_list_head()* \param	name:	要定义的链表节点名*/
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name)	\struct list_head name = LIST_HEAD_INIT(name)/** 为链表的实际应用留下扩展接口 *//*** \brief	获取一个结构体中的某个成员相对于结构体首地址的偏移量* \details	用于操作链表上层的带有有效数据+链表成员的结构体* \remarks	在stddef.h中已有该宏定义函数* \param	TYPE:	上层结构体名称* \param	MEMBER:	结构体中要查找偏移量的成员,一般这个成员是链表结构体指针* \return	结构体成员相对于结构体首地址的偏移量*/
#undef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)/*** \brief	从结构体中某一成员地址逆推出该结构体的首地址* \details	用于操作链表上层的带有有效数据+链表成员的结构体* \note	typeof是Linux GNU C(GCC)中扩展的关键字,从定义的变量名逆推出该变量的*			类型,如int a; typeof(a) b;中的第二句与int b;的效果相同;*			在Windows等其它编译器中编译会不通过;*			原始定义在include/linux/kernel.h中* \param	ptr:	需要逆推的上层结构体中的某个成员地址,一般是链表成员的地址* \param	type:	上层结构体的类型名,一般该类型是结构体* \param	member:	上层结构体中成员地址的名称,也就是a.b或a->b里面的这个b*/
#define container_of(ptr, type, member) ({					\const typeof( ((type *)0)->member ) *__mptr = (ptr);	\(type *)( (char *)__mptr - offsetof(type,member) );})/*** \brief	获取已嵌入链表结构体的上层结构体地址* \param	ptr:	上层结构体中的&struct list_head指针* \param	type:	嵌入了list_head成员的上层结构体类型名* \param	member:	上层结构体中list_head所属的名称*/
#define list_entry(ptr, type, member)	\container_of(ptr, type, member)/*** \brief	获取链表入口所在链表第一个元素对应的上层结构体地址* \note	调用前必须确保该链表非空* \param	ptr:	上层结构体中的&struct list_head指针,该指针是个链表入口* \param	type:	嵌入了list_head成员的上层结构体类型名* \param	member:	上层结构体中list_head所属的名称*/
#define list_first_entry(ptr, type, member) \list_entry((ptr)->next, type, member)/*** \brief	循环整个链表时的for(;x;x)语句(循环时不能删除当前链表节点)* \param	pos:	当前循环到的节点,是个临时变量* \param	head:	链表入口*/
#define list_for_each(pos, head)	\for (pos = (head)->next; pos != (head); pos = pos->next)/*** \brief	循环整个链表时的for(;x;x)语句(循环时可以删除当前链表节点)* \param	pos:	当前循环到的节点,是个临时变量* \param	n:		作为临时变量的节点* \param	head:	链表入口*/
#define list_for_each_safe(pos, n, head)					\for (pos = (head)->next, n = pos->next; pos != (head);	\pos = n, n = pos->next)/*** \brief	在上层结构体的基础上循环整个链表时的for(;x;x)语句(循环时不能删除当前链表节点)* \details	虽然是在上层带有效数据的结构体指针上进行循环,但是实际实现时*			是以其中的链表结构体作为依据* \param	pos:	要循环的上层结构体临时变量,该结构体中带有链表成员,*					pos值用作变量,本身不必预先赋值,但是循环时不能删除它* \param	head:	上层结构体中的list_head成员的地址* \param	member:	上层结构体中的list_head成员的名称* \note	head虽然是链表入口地址,但本身是尾(最后弹出)地址,head->next是头(最先弹出)地址;*/
#define list_for_each_entry(pos, head, member)					\for (pos = list_entry((head)->next, typeof(*pos), member);	\&pos->member != (head);								\pos = list_entry(pos->member.next, typeof(*pos), member))/*** \brief	在上层结构体的基础上循环整个链表时的for(;x;x)语句(支持循环时删除当前链表节点)* \details	虽然是在上层带有效数据的结构体指针上进行循环,但是实际实现时*			是以其中的链表结构体作为依据* \param	pos:	要循环的上层结构体临时变量,该结构体中带有链表成员,*					pos值用作变量,本身不必预先赋值,循环时可以删除它* \param	n:		上层结构体临时变量* \param	head:	上层结构体中的list_head成员的地址* \param	member:	上层结构体中的list_head成员的名称* \note	head虽然是链表入口地址,但本身是尾(最后弹出)地址,head->next是头(最先弹出)地址;*/
#define list_for_each_entry_safe(pos, n, head, member)			\for (pos = list_entry((head)->next, typeof(*pos), member),	\n = list_entry(pos->member.next, typeof(*pos), member);\&pos->member != (head);								\pos = n, n = list_entry(n->member.next, typeof(*n), member))/* 因为下面都是内联函数,所以无需放在.c中,放在.h中即可,编译时不会重复编译,而是会像宏定义一样内联展开*//** 私有函数 *//*** \brief	在链表序列中插入一个链表节点(已知要插入位置的之前和之后的节点)* \param	_new:	要插入的链表节点* \param	prev:	插入点前方的链表节点* \param	next:	插入点后方的链表节点*/
static inline void __list_add(struct list_head *_new,struct list_head *prev,struct list_head *next)
{next->prev = _new;_new->next = next;_new->prev = prev;prev->next = _new;
}/*** \brief	在链表序列中删除一个链表节点(已知要删除位置的之前和之后的节点)* \param	prev:	删除点前方的链表节点* \param	next:	删除点后方的链表节点*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{next->prev = prev;prev->next = next;
}/*** \brief	在链表序列中删除一个链表入口节点* \param	entry:	要删除的链表节点*/
static inline void __list_del_entry(struct list_head *entry)
{__list_del(entry->prev, entry->next);
}/* 接口函数 *//*** \brief	初始化一个链表节点* \param	list:	要初始化的链表指针*/
static inline void init_list_head(struct list_head *list)
{list->next = list;list->prev = list;
}/*** \brief	在链表序列中删除一个链表入口节点,并重新初始化这个链表入口* \param	entry:	要删除的链表节点*/
static inline void list_del_init(struct list_head *entry)
{__list_del_entry(entry);init_list_head(entry);
}/*** \brief	判断链表是否为空* \param	head:	要判断的链表指针*/
static inline int list_empty(const struct list_head *head)
{return head->next == head;
}/*** \brief	判断链表是否为空(在多核CPU上较安全)* \param	head:	要判断的链表指针* \return	为空时返回真,不为空返回假*/
static inline int list_empty_careful(const struct list_head *head)
{struct list_head *next = head->next;return (next == head) && (next == head->prev);
}/*** \brief	将一个链表节点插入到一条链表的头部,先入后出* \param	new:	要插入的链表节点* \param	head:	要加入的那条链表的链表入口*					(链表入口所属的那个节点是链表尾,head->next是链表头)*/
static inline void list_add(struct list_head *new, struct list_head *head)
{__list_add(new, head, head->next);
}/*** \brief	将一个链表节点插入到链表尾,先入先出* \details	也就是更新了这条链表入口节点的前一个(入口并不是链表头)* \param	_new:	要插入的链表节点* \param	head:	要加入的那条链表的链表入口*					(链表入口所属的那个节点是链表尾,head->next是链表头)*/
static inline void list_add_tail(struct list_head *_new, struct list_head *head)
{__list_add(_new, head->prev, head);
}/* 用于让销毁的链表节点指向一个未使用地址 */
#define LIST_POISON	((void *)0x0)/*** \brief	将一个链表节点从它自己所属的这条链表中删除* \param	entry:	要删除的链表节点*/
static inline void list_del(struct list_head *entry)
{__list_del(entry->prev, entry->next);entry->next = (struct list_head *)LIST_POISON;entry->prev = (struct list_head *)LIST_POISON;
}#endif /* LIST_H */
  • util_errno.h
/******************************************************************************* \brief	错误码* \note	基于linux_6.1-rc4\include\uapi\asm-generic\errno-base.h*				linux_6.1-rc4\tools\arch\alpha\include\uapi\asm\errno.h*				linux_6.1-rc4\include\linux\errno.h* \author	中文注释:将狼才鲸* \date	2023-03-04******************************************************************************/#ifndef _UTIL_ERRNO_H_
#define _UTIL_ERRNO_H_/*********************************** 宏定义 ***********************************/
#define	EPERM		 1	/* 操作不允许 */
#define	ENOENT		 2	/* 没有此文件或目录 */
#define	ESRCH		 3	/* 进程不存在 */
#define	EINTR		 4	/* 系统调用被中断,Interrupted system call */#define	EIO			 5	/* 读写错误,I/O error */
#define	ENXIO		 6	/* 没有此设备或地址 */
#define	E2BIG		 7	/* 参数列表太长 */
#define	ENOEXEC		 8	/* 执行格式错误,Exec format error */
#define	EBADF		 9	/* 错误的文件号,Bad file number */
#define	ECHILD		10	/* 没有该子进程,No child processes */#define	ENOMEM		12	/* 内存不足,Out of memory */
#define	EACCES		13	/* 没有权限 */
#define	EFAULT		14	/* 非法地址,Bad address */
#define	ENOTBLK		15	/* 没有块设备,Block device required */
#define	EBUSY		16	/* 设备或资源忙,Device or resource busy */
#define	EEXIST		17	/* 文件已存在,File exists */
#define	EXDEV		18	/* 链接不在同一个设备,Cross-device link */
#define	ENODEV		19	/* 无此设备,No such device */
#define	ENOTDIR		20	/* 不是文件夹,Not a directory */
#define	EISDIR		21	/* 是文件夹,Is a directory */#define	EINVAL		22	/* 参数非法,Invalid argument */
#define	ENFILE		23	/* 文件表溢出,File table overflow */
#define	EMFILE		24	/* 文件打开太多,Too many open files */
#define	ENOTTY		25	/* 不是字符设备,Not a typewriter */
#define	ETXTBSY		26	/* 文本文件忙,Text file busy */
#define	EFBIG		27	/* 文件太大,File too large */
#define	ENOSPC		28	/* 设备空间不足,No space left on device */
#define	ESPIPE		29	/* 非法跳转,Illegal seek */
#define	EROFS		30	/* 文件系统只读,Read-only file system */
#define	EMLINK		31	/* 链接太多,Too many links */
#define	EPIPE		32	/* 管道损坏,Broken pipe */
#define	EDOM		33	/* 参数超出函数范围,Math argument out of domain of func */
#define	ERANGE		34	/* 结果不能表示,超出范围 */#define	EAGAIN		35	/* 请重试,Try again */
#define	EWOULDBLOCK	EAGAIN	/* 操作被阻塞,Operation would block */
#define	EINPROGRESS	36	/* 操作正在处理中,Operation now in progress */
#define	EALREADY	37	/* 操作已就绪,Operation already in progress */
#define	ENOTSOCK	38	/* Socket operation on non-socket */
#define	EDESTADDRREQ	39	/* 需要目的地址,Destination address required */
#define	EMSGSIZE	40	/* 消息太长,Message too long */
#define	EPROTOTYPE	41	/* 协议类型错误,Protocol wrong type for socket */
#define	ENOPROTOOPT	42	/* 协议不可用,Protocol not available */
#define	EPROTONOSUPPORT	43	/* 协议不支持,Protocol not supported */
#define	ESOCKTNOSUPPORT	44	/* Socket类型不支持,Socket type not supported */
#define	EOPNOTSUPP	45	/* 在该传输端点上操作不支持,Operation not supported on transport endpoint */
#define	EPFNOSUPPORT	46	/* 协议族不支持,Protocol family not supported */
#define	EAFNOSUPPORT	47	/* 地址族不支持,Address family not supported by protocol */
#define	EADDRINUSE	48	/* 地址已在使用,Address already in use */
#define	EADDRNOTAVAIL	49	/* 所请求的地址无法分配,Cannot assign requested address */
#define	ENETDOWN	50	/* 网络已断开,Network is down */
#define	ENETUNREACH	51	/* 网络无法访问,Network is unreachable */
#define	ENETRESET	52	/* 因为复位导致网络连接中断,Network dropped connection because of reset */
#define	ECONNABORTED	53	/* 连接中止,Software caused connection abort */
#define	ECONNRESET	54	/* 连接复位,Connection reset by peer */#define	ENOBUFS		55	/* 没有可用的缓存,No buffer space available */
#define	EISCONN		56	/* 传输端点已连接,Transport endpoint is already connected */
#define	ENOTCONN	57	/* 传输端点未连接,Transport endpoint is not connected */
#define	ESHUTDOWN	58	/* 传输端点关闭后无法发送,Cannot send after transport endpoint shutdown */
#define	ETOOMANYREFS	59	/* 引用太多无法拼接,Too many references: cannot splice */
#define	ETIMEDOUT	60	/* 连接超时,Connection timed out */
#define	ECONNREFUSED	61	/* 连接被拒绝,Connection refused */
#define	ELOOP		62	/* 符号连接冲突太多 */
#define	ENAMETOOLONG	63	/* 文件名太长,File name too long */
#define	EHOSTDOWN	64	/* 主机已关闭,Host is down */
#define	EHOSTUNREACH	65	/* 主机无路由,No route to host */
#define	ENOTEMPTY	66	/* 文件夹非空,Directory not empty */
#define	EUSERS		68	/* 用户太多,Too many users */#define	EDQUOT		69	/* 超出界限,Quota exceeded */
#define	ESTALE		70	/* 旧的文件句柄,Stale file handle */
#define	EREMOTE		71	/* 目标已移除,Object is remote */
#define	ENOLCK		77	/* 没有可用的锁,No record locks available */
#define	ENOSYS		78	/* 函数未实现 */
#define	ENOMSG		80	/* 没有所需类型的消息,No message of desired type */
#define	EIDRM		81	/* 标识符已删除,Identifier removed */
#define	ENOSR		82	/* 没有流资源,Out of streams resources */
#define	ETIME		83	/* 定时器超时,Timer expired */
#define	EBADMSG		84	/* 不是数据消息 */
#define	EPROTO		85	/* 协议错误,Protocol error */#define	ENODATA		86	/* 没有可用的数据,No data available */
#define	ENOSTR		87	/* 不是流设备,Device not a stream */
#define	ENOPKG		92	/* 包未安装,Package not installed */
#define	EILSEQ		116	/* 字节序列非法Illegal byte sequence */
#define	ECHRNG		88	/* 通道号超出范围,Channel number out of range */
#define	EL2NSYNC	89	/* 级别2未同步,Level 2 not synchronized */
#define	EL3HLT		90	/* 级别3中止,Level 3 halted */
#define	EL3RST		91	/* 级别3复位,Level 3 reset */
#define	ELNRNG		93	/* 链接号超出范围,Link number out of range */
#define	EUNATCH		94	/* 协议驱动未附加,Protocol driver not attached */
#define	ENOCSI		95	/* CSI结构不可用,No CSI structure available */
#define	EL2HLT		96	/* 级别2中止,Level 2 halted */
#define	EBADE		97	/* 无效的交换 */
#define	EBADR		98	/* 无效的请求描述符 */
#define	EXFULL		99	/* 交换已满,Exchange full */
#define	ENOANO		100	/* 没有正极,No anode */
#define	EBADRQC		101	/* 请求码无效,Invalid request code */
#define	EBADSLT		102	/* Invalid slot */
#define	EDEADLK		11	/* 将发生资源死锁,Resource deadlock would occur */
#define	EDEADLOCK	EDEADLK	/* 发生死锁 */
#define	EBFONT		104	/* 字库文件格式错误,Bad font file format */
#define	ENONET		105	/* 设备未联网,Machine is not on the network */
#define	ENOLINK		106	/* 链路已断,Link has been severed */
#define	EADV		107	/* 广播错误,Advertise error */
#define	ESRMNT		108	/* 挂载错误,Srmount error */
#define	ECOMM		109	/* 发送时通信错误,Communication error on send */
#define	EMULTIHOP	110	/* 尝试多跳,Multihop attempted */
#define	EDOTDOT		111	/* RFS specific error */#define	EOVERFLOW	112	/* 参数溢出,对于已定义的数据类型来说值太大 */
#define	ENOTUNIQ	113	/* 名称在网络上不唯一,Name not unique on network */
#define	EBADFD		114	/* 文件描述符处于非法状态,File descriptor in bad state */
#define	EREMCHG		115	/* 远端地址已改变,Remote address changed */
#define	EUCLEAN		117	/* 结构需要清理,Structure needs cleaning */
#define	ENOTNAM		118	/* 不是由XENIX命名的类型文件,Not a XENIX named type file */
#define	ENAVAIL		119	/* 没有可用的XENIX信号量,No XENIX semaphores available */
#define	EISNAM		120	/* 是一个已命名的文件,Is a named type file */
#define	EREMOTEIO	121	/* 远端读写错误,Remote I/O error */
#define	ELIBACC		122	/* 无法访问所需的共享库,Can not access a needed shared library */
#define	ELIBBAD		123	/* 访问的共享库已损坏,Accessing a corrupted shared library */
#define	ELIBSCN		124	/* a.out中的.lib部分已损坏,.lib section in a.out corrupted */
#define	ELIBMAX		125	/* 试图链接的共享库太多,Attempting to link in too many shared libraries */
#define	ELIBEXEC	126	/* 不能直接运行共享库,Cannot exec a shared library directly */#define	ERESTART	127	/* 应重新启动已中断的系统调用,Interrupted system call should be restarted */
#define	ESTRPIPE	128	/* 流管道错误,Streams pipe error */
#define ENOMEDIUM	129	/* 找不到介质,No medium found */
#define EMEDIUMTYPE	130	/* 错误的介质类型,Wrong medium type */#define	ECANCELED	131	/* 操作已取消,Operation Cancelled */
#define	ENOKEY		132	/* 所需键值不可用,Required key not available */
#define	EKEYEXPIRED	133	/* 密钥已过期,Key has expired */
#define	EKEYREVOKED	134	/* 密钥已吊销,Key has been revoked */
#define	EKEYREJECTED	135	/* 密钥被服务拒绝,Key was rejected by service */
#define	EOWNERDEAD	136	/* 拥有者已注销,Owner died */
#define	ENOTRECOVERABLE	137	/* 状态不可恢复,State not recoverable */
#define	ERFKILL		138	/* Operation not possible due to RF-kill */
#define EHWPOISON	139	/* 内存页硬件错误,Memory page has hardware error */
#define ERESTARTSYS	512	/* 系统重启 */
#define ERESTARTNOINTR	513	/* 无中断的系统重启 */
#define ERESTARTNOHAND	514	/* 无处理句柄的重启,restart if no handler.. */
#define ENOIOCTLCMD	515	/* 命令不存在,No ioctl command */
#define ERESTART_RESTARTBLOCK 516 /* 系统调用的重启,restart by calling sys_restart_syscall */
#define EPROBE_DEFER	517	/* 驱动需要重新探测,Driver requests probe retry */
#define EOPENSTALE	518	/* 打开时发现了一个旧入口,open found a stale dentry */#define ENOPARAM	519	/* 参数不支持,Parameter not supported */
#define EBADHANDLE	521	/* 非法的NFS文件句柄,Illegal NFS file handle */
#define ENOTSYNC	522	/* 更新同步不匹配,Update synchronization mismatch */
#define EBADCOOKIE	523	/* Cookie太陈旧,Cookie is stale */#define ENOTSUPP	524	/* 操作不支持,Operation is not supported */
#define ETOOSMALL	525	/* 缓存或请求太小,Buffer or request is too small */
#define ESERVERFAULT	526	/* 无法翻译,An untranslatable error occurred */
#define EBADTYPE	527	/* 服务器不支持的类型,Type not supported by server */
#define EJUKEBOX	528	/* 请求超时,Request initiated, but will not complete before timeout */
#define EIOCBQUEUED	529	/* io回调已推入队列,将得到完成标志,iocb queued, will get completion event */
#define ERECALLCONFLICT	530	/* 回调状态冲突,conflict with recalled state */
#define ENOGRACE	531	/* 拒绝取回NFS文件锁,NFS file lock reclaim refused */#endif /* _UTIL_ERRNO_H_ *//*********************************** 文件尾 ***********************************/

相关文章:

01 C语言使用链表实现队列(Queue、FIFO)模块

01 C语言使用链表实现队列&#xff08;Queue、FIFO&#xff09;模块 作者将狼才鲸创建日期2023-03-08Gitee源码仓库地址&#xff1a;C语言使用链表实现队列&#xff08;Queue、FIFO&#xff09;模块 Linux原生的队列KFIFO一次只能操作一个队列&#xff0c;操作变长元素时&…...

2.2操作系统-进程管理:前趋图、前趋图与PV操作

2.1操作系统-进程管理&#xff1a;前趋图\前趋图与PV操作前趋图前趋图与PV操作练习前趋图与PV操作&#xff0c;一般出现了&#xff0c;分值在2~3分左右&#xff0c;技巧性很强。 前趋图 前趋图是为了描述一个程序的各部分间的依赖关系&#xff0c;或者是一个大的计算的各个子…...

凤凰游攻略

凤凰游攻略1 装备&#x1f4e6;1.1 证件1.2 日常用品1.3 药品1.4 衣物1.5 洗漱用品2 交通&#x1f697;3 住宿&#x1f3e0;4 美食&#x1f355;5 拍照&#x1f4f7;5.1 租苗族服5.1.1 单租服装5.1.2 服装化妆5.2 一条龙旅拍6 路线&#x1f5fa;️景点&#x1f3d9;️7 注意⚠️…...

Nginx 高可用方案

准备工作 10.10.4.5 10.10.4.6 VIP&#xff1a;10.10.4.10 两台虚拟机。安装好Nginx 安装Nginx 更新yum源文件&#xff1a; rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm wget -O /etc/yum.repos.d/CentOS-Ba…...

Linux基本指令

文章目录 常用Linux命令常见Linux指令 1、ls指令 语法&#xff1a;ls [选项][目录或文件] 功能&#xff1a;对于目录&#xff0c;该命令列出该目录下的所有子目录与文件。对于文件&#xff0c;将列出文件名以及其他信息。常用选项&#xff1a; -a 列出目录下的所有文件&#xf…...

Linux系统基础命令(二)

一、浏览和切换目录 ls命令&#xff1a;列出文件和目录&#xff0c;主要用于列出文件和目录 CentOS的终端默认是有颜色标注的。一般来说&#xff1a;蓝色--->目录&#xff1b;绿色-->可执行文件&#xff1b;红色--->压缩文件&#xff1b;浅蓝色--->链接文件&#…...

【C++】C++11——简介|列表初始|简化声明|nullptr与范围for|STL中的变化

文章目录一、C11简介二、列表初始化三、简化声明四、nullptr与范围for五、STL中一些变化一、C11简介 在2003年C标准委员会曾经提交了一份技术勘误表(简称TC1)&#xff0c;使得C03这个名字已经取代了C98称为C11之前的最新C标准名称。不过由于TC1主要是对C98标准中的漏洞进行修复…...

Python -- 函数

文章目录1、一个简单的函数2、多参数函数3、返回值3.1、简单的返回3.2、返回列表和字典4、传入列表5、传入任意数量的实参5.1、以元组和字典的形式5.2、形参的排列顺序6、将函数储存在模块中1、一个简单的函数 函数用关键字def来定义&#xff0c;传参时不用指定参数类型 para&…...

Pytorch中utils.data 与torchvision简介

Pytorch中utils.data 与torchvision简介1 数据处理工具概述2 utils.data简介3 torchvision简介3.1 transforms3.2 ImageFolder1 数据处理工具概述 Pytorch涉及数据处理&#xff08;数据装载、数据预处理、数据增强等&#xff09;主要工具包及相互关系如下图所示&#xff0c;主…...

学习 Python 之 Pygame 开发魂斗罗(十)

学习 Python 之 Pygame 开发魂斗罗&#xff08;十&#xff09;继续编写魂斗罗1. 解决敌人不开火的问题2. 创建爆炸效果类3. 为敌人跳入河中增加爆炸效果4. 玩家击中敌人继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗&#xff08;九&#xff09;中&#xff0c;…...

Keepalive+LVS群集部署

KeepaliveLVS群集部署一、Keepalive概述1、什么是Keepalive2、Keepalive工作原理3、Keepalive主要模块及作用4、Keepalived 服务重要功能&#xff08;1&#xff09;管理 LVS 负载均衡软件&#xff08;2&#xff09;支持故障自动切换&#xff08;3&#xff09;实现 LVS 负载调度…...

数组、指针总结【面试题】

文章目录0. 补充知识数组笔试题1. 一维数组1.1 字符数组1.1.1 sizeof1.1.2 strlen1.2 二维数组2. 指针笔试题0. 补充知识 在进入数组与指针的练习时&#xff0c;我们先来复习以下以下的知识点&#xff0c;这可以帮助我们更好的理解下面练习 数组是一组能存放相同类型的类型的元…...

七色电子标签

机种名 电子会议桌牌 型号 ESL_7color_7.3_D 外观尺寸 176.2x137.15x80mm 产品重量 268g 可视区域 163.297.92mm 外观颜色 银色 供电方式 锂电池供电2300mAh&#xff08;Type-C 接口可充电&#xff09; 显示技术 E-INK电子纸&#xff0c;双屏 像素 800x480 像…...

大数据是什么?发展前景怎么样

关于大数据的解释&#xff0c;比较官方的定义是指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。简单来说&#xff0c;大数据就是结构化…...

MYSQL必知必会 | 查询相关

汇总数据 聚集函数 有时只需要汇总数据&#xff0c;并不需要把数据实际检索出来&#xff0c;所以MySql提供了专门的函数 聚集函数&#xff1a;运行在行组上&#xff0c;计算和返回单个值的函数 函数说明AVG()返回某列平均值COUNT()返回某列的行数MAX()返回某列最大值MIN()返…...

Java学习环境一站说明(保姆级详细教学)

1.Java开发环境搭建官网下载www.oracle.com2.安装注意&#xff1a;1.选择安装位置时尽量不要安装到C盘&#xff0c;路径中不要有空格以及中文的存在2.开发人员安装的jdk中包含了jre&#xff0c;所以不需要单独安装jre3.环境变量配置打开高级系统设置2.点击环境变量3.在系统变量…...

05-Oracle中的对象(视图,索引,同义词,系列)

本章主要内容&#xff1a; 1.视图管理&#xff1a;视图新增&#xff0c;修改&#xff0c;删除&#xff1b; 2.索引管理&#xff1a;索引目的&#xff0c;创建&#xff0c;修改&#xff0c;删除&#xff1b; 3.同义词管理&#xff1a;同义词的作用&#xff0c;创建&#xff0…...

如何通过websoket实现即时通讯+断线重连?

本篇博客只是一个demo&#xff0c;具体应用还要结合项目实际情况&#xff0c;以下是目录结构&#xff1a; 1.首先通过express搭建一个本地服务器 npm install express 2.在serve.js中自定义测试数据 const express require(express); const app express(); const http req…...

爽,我终于掌握了selenium图片滑块验证码

因为种种原因没能实现愿景的目标&#xff0c;在这里记录一下中间结果&#xff0c;也算是一个收场吧。这篇文章主要是用selenium解决滑块验证码的个别案列。 思路&#xff1a; 用selenium打开浏览器指定网站 将残缺块图片和背景图片下载到本地 对比两张图片的相似地方&#x…...

二、SpringMVC注解式开发

1. RequestMapping注解 此注解就是来映射服务器访问的路径 可加在方法上,是为此方法注册一个可以访问的名称(路径) 可以加在类上,相当于是包名(虚拟路径),区分不同类中相同的action的名称 可区分get请求和post请求 package com.powernode.controller;import org.springframe…...

Java容器面试知识点总结

容器 java容器有哪些&#xff1f; String&#xff0c;数组以及Java.util 下面的集合类 List&#xff1a;存放有序&#xff0c;列表存储&#xff0c;元素可重复 ArrayList LinkedList Vector Set:无序&#xff0c;元素不可重复 HashSet TreeSet Map: 无序&#xff0c;元素可重复…...

增长:2023 IT运维发展趋势前瞻

根据IDC和智研咨询数据等平台公开数据显示&#xff0c;从2018年至2022年&#xff0c;全球ITOM行业市场规模以8.58%的年均复合增长率高速增长。其中&#xff0c;中国ITOM市场在2020-2023年的年复合增长率为10.7%&#xff0c;到2023年市场规模将达到165.7亿元。012022中国IT运维解…...

自己定义typescript的类型声明文件xx.d.ts

****内容预警***菜鸟新手内容&#xff0c;大佬请绕道&#xff0c;不对的请指出我们在使用typescript的使用&#xff0c;如果安装一个包没有相应的类型声明文件&#xff0c;ts的类型检查就会报错&#xff0c;所以我们经常会安装npm包对应的types类型声明包&#xff0c;比如uuid …...

数据分析方法及名词解释总结_(面试2)

1、用户画像 1.1、什么是用户画像&#xff1f;如何构建用户画像&#xff1f; - 知乎提到用户画像&#xff0c; 很多人都可能存在的错误认知&#xff0c;即把用户画像简单理解成用户各种特征&#xff0c;比如说姓名、性别、…https://www.zhihu.com/question/372802348/answer/2…...

【FLY】Java知识点总结

目录认识Java概念图名词解释历史版本基础知识编程规范关键字数据类型运算符数组Stringequals与流程控制引用数据结构常用数据结构HashMapLinkedHashMapWeakHashMapIdentityHashMapEnumMapTreeMapCopyOnWriteArrayList面向对象类反射注解IO异常线程EffectiveJava8JVM运行时数据区…...

SpringMVC-0307

三、RequestMapping注解1、RequestMapping注解的功能从注解名称上我们可以看到&#xff0c;RequestMapping注解的作用就是将请求和处理请求的控制器方法关联起来&#xff0c;建立映射关系。SpringMVC 接收到指定的请求&#xff0c;就会来找到在映射关系中对应的控制器方法来处理…...

华为OD机试 - 九宫格按键输入(C 语言解题)【独家】

最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 使用说明本期题目:九宫格按…...

Oracle 11g RAC群集部署

Oracle 11g RAC群集部署 1.环境介绍&#xff1a; 操作系统&#xff1a;Oracle Enterprise Linux 6.5 Oracle数据库&#xff1a;Oracle 11.2.0.4 集群软件&#xff1a;Oracle Grid Infrastructure 11.2.0.4 2.所需介质&#xff1a; p13390677_112040_Linux-x86-64_1of7 p133…...

【C++、C++11】列表初始化、右值引用

文章目录&#x1f4d6; 前言1. 统一的列表初始化1.1 { } 花括号初始化&#xff1a;1.2 std::initializer_list&#xff1a;2. 右值引用2.1 什么是左值和右值&#xff1a;2.2 右值的分类&#xff1a;2.3 左值引用和右值引用的比较2.3 右值的使用场景&#xff1a;2.4 新的类功能&…...

CMU15-445 Project.3总结

在线测试 Project #3 - Query Execution 以下是Project #3的网址&#xff0c;2022FALL的Project #3是实现一个查询执行&#xff0c;实现一系列算子&#xff0c;用于实现数据库内的SQL计算。项目中的 Query Execution 主要分为三个任务&#xff1a; Access Method Executors…...