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.c

jim@DESKTOP-SVP3BEM MINGW64 /d/1_git/many-repositories/26_队列_缓存 (develop)
$ make run
./demo

put:
0
1
2
3
4
5
6
7

get:
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7

jim@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 	/* memcpy */
#include 	/* 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 	/* NULL */

#if 0//defined(TARGET_LINUX32) || defined(TARGET_LINUX64)	\
	|| defined(_MSC_VER) || defined(WIN32) || defined(_WIN64)
	/* 如果在操作系统之中,需要上锁 */
#	include 
	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 	/* 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_ */

/*********************************** 文件尾 ***********************************/

你可能感兴趣的:(12,嵌入式/单片机编程技巧,c语言,嵌入式,linux,单片机,驱动开发)