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语言使用链表实现队列(Queue、FIFO)模块 作者将狼才鲸创建日期2023-03-08Gitee源码仓库地址:C语言使用链表实现队列(Queue、FIFO)模块 Linux原生的队列KFIFO一次只能操作一个队列,操作变长元素时&…...

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

凤凰游攻略
凤凰游攻略1 装备📦1.1 证件1.2 日常用品1.3 药品1.4 衣物1.5 洗漱用品2 交通🚗3 住宿🏠4 美食🍕5 拍照📷5.1 租苗族服5.1.1 单租服装5.1.2 服装化妆5.2 一条龙旅拍6 路线🗺️景点🏙️7 注意⚠️…...

Nginx 高可用方案
准备工作 10.10.4.5 10.10.4.6 VIP:10.10.4.10 两台虚拟机。安装好Nginx 安装Nginx 更新yum源文件: 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指令 语法:ls [选项][目录或文件] 功能:对于目录,该命令列出该目录下的所有子目录与文件。对于文件,将列出文件名以及其他信息。常用选项: -a 列出目录下的所有文件…...

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

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

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

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

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

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

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

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

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

MYSQL必知必会 | 查询相关
汇总数据 聚集函数 有时只需要汇总数据,并不需要把数据实际检索出来,所以MySql提供了专门的函数 聚集函数:运行在行组上,计算和返回单个值的函数 函数说明AVG()返回某列平均值COUNT()返回某列的行数MAX()返回某列最大值MIN()返…...

Java学习环境一站说明(保姆级详细教学)
1.Java开发环境搭建官网下载www.oracle.com2.安装注意:1.选择安装位置时尽量不要安装到C盘,路径中不要有空格以及中文的存在2.开发人员安装的jdk中包含了jre,所以不需要单独安装jre3.环境变量配置打开高级系统设置2.点击环境变量3.在系统变量…...

05-Oracle中的对象(视图,索引,同义词,系列)
本章主要内容: 1.视图管理:视图新增,修改,删除; 2.索引管理:索引目的,创建,修改,删除; 3.同义词管理:同义词的作用,创建࿰…...

如何通过websoket实现即时通讯+断线重连?
本篇博客只是一个demo,具体应用还要结合项目实际情况,以下是目录结构: 1.首先通过express搭建一个本地服务器 npm install express 2.在serve.js中自定义测试数据 const express require(express); const app express(); const http req…...

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

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

Java容器面试知识点总结
容器 java容器有哪些? String,数组以及Java.util 下面的集合类 List:存放有序,列表存储,元素可重复 ArrayList LinkedList Vector Set:无序,元素不可重复 HashSet TreeSet Map: 无序,元素可重复…...

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

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

数据分析方法及名词解释总结_(面试2)
1、用户画像 1.1、什么是用户画像?如何构建用户画像? - 知乎提到用户画像, 很多人都可能存在的错误认知,即把用户画像简单理解成用户各种特征,比如说姓名、性别、…https://www.zhihu.com/question/372802348/answer/2…...

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

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

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

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

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

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