errno用法(erroneous用法)

http://www.itjxue.com  2023-02-24 18:10  来源:未知  点击次数: 

如何用errno判断msgrcv的返回值

msgrcv/msgsnd为linux系统中异步或进程间通信的一种机制,这两个函数主要用于操作特定的消息队列。msgrcv()可以从消息队列中读取消息,msgsnd()将一个新的消息写入队列。

msgrcv()可以从消息队列中读取消息,msgsnd()将一个新的消息写入队列。

在消息队列上进行收发消息。为了发送消息,调用进程对消息队列进行写入时必须有写权能。接收消息时必须有读权能。

用法

#include sys/types.h

#include sys/ipc.h

#include sys/msg.h

函数原型

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

参数

msqid:消息队列的识别码。

msgp:指向消息缓冲区的指针,此位置用来暂时存储发送和接收的消息,是一个用户可定义的通用结构,形态如下

struct msgbuf {

long mtype; /* 消息类型,必须 0 */

char mtext[1]; /* 消息文本 */

};

msgsz:消息的大小。

msgtyp:消息类型

msgtyp等于0 则返回队列的最早的一个消息。

msgtyp大于0,则返回其类型为mtype的第一个消息。

msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。

msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。如果不指定这个参数,那么进程将被阻塞直到函数可以从队列中得到符合条件的消息为止。如果一个client 正在等待消息的时候队列被删除,EIDRM 就会被返回。如果进程在阻塞等待过程中收到了系统的中断信号,EINTR 就会被返回。MSG_NOERROR,如果函数取得的消息长度大于msgsz,将只返回msgsz 长度的信息,剩下的部分被丢弃了。如果不指定这个参数,E2BIG 将被返回,而消息则留在队列中不被取出。当消息从队列内取出后,相应的消息就从队列中删除了。

返回说明

成功执行时,msgsnd()返回0,msgrcv()返回拷贝到mtext数组的实际字节数。失败两者都返回-1,errno被设为以下的某个值

[对于msgsnd]

EACCES:调用进程在消息队列上没有写权能,同时没有CAP_IPC_OWNER权能

EAGAIN:由于消息队列的msg_qbytes的限制和msgflg中指定IPC_NOWAIT标志,消息不能被发送

EFAULT:msgp指针指向的内存空间不可访问

EIDRM:消息队列已被删除

EINTR:等待消息队列空间可用时被信号中断

EINVAL:参数无效

ENOMEM:系统内存不足,无法将msgp指向的消息拷贝进来

[对于msgrcv]

E2BIG:消息文本长度大于msgsz,并且msgflg中没有指定MSG_NOERROR

EACCES:调用进程没有读权能,同时没具有CAP_IPC_OWNER权能

EAGAIN:消息队列为空,并且msgflg中没有指定IPC_NOWAIT

EFAULT:msgp指向的空间不可访问

EIDRM:当进程睡眠等待接收消息时,消息已被删除

EINTR:当进程睡眠等待接收消息时,被信号中断

EINVAL:参数无效

ENOMSG:msgflg中指定了IPC_NOWAIT,同时所请求类型的消息不存在

请教标准C中errno的定义和用途及用法

定义在 ERRNO.H ERRCPP.H ERRCPPD.H ERROR.H ERRORS.H

等头文件中。

例如:号码7 是 E2BIG,意思是 变量表太长,超过 128 bytes.头文件中有

#define E2BIG 7

例如:sqrt(-1) 得到 EDOM,负数开平方错误

#define EDOM 33

不同的编译器定义的号码可能不同。

一般用于系统调用时得到调用失败指示信息(status),然后用查错误函数(例如 GetErrorInfo )查出是什么错。

Epoll用法及读写触发条件

一、函数解析

1. size不是最大值,而是内核如何对内部结构进行维度设置的提示。

2. epoll_create返回的文件描述符必须使用close关闭。

返回值:成功(非负文件描述符) 失败(-1)

errno(EINVAL-size非正 | ENFILE-文件描述符用完 | ENOMEM-内存不足)

events成员有:

EPOLLIN 关联的文件描述符可读

EPOLLOUT 关联的文件描述符可写

EPOLLRDHUP 流式套接字对端关闭连接或关闭写通道(ET模式写非常有用)2.6.17

EPOLLPRI 关联的文件描述符紧急数据可读

EPOLLERR 关联的文件描述符发生错误

EPOLLHUP? 关联的文件描述符挂起

EPOLLET ET模式

EPOLLONESHOT 关联的文件描述符设置一次性行为 2.6.2

op操作有:

EPOLL_CTL_ADD 增加

EPOLL_CTL_MOD 修改

EPOLL_CTL_DEL 删除

返回值:成功(0) 失败(-1)

errno(EBADF-epfd或者fd不是合法的 | EEXIST-重复增加 | EINVAL-epfd不是epoll描述符或者epfd=fd | ENOENT-修改删除的fd不在epoll中 | ENOMEM-内存不足 | EPERM-fd不支持epoll)

1. timeout为0表示立马返回, 为-1表示无限等待

2. 超时或者达到maxevents都会返回

返回值:成功(就绪的文件描述符数量) 失败(-1)

errno(EBADF-epfd不合法 | EFAULT-events没有写权限 | EINTR-超时 | EINVAL-epfd不是epoll描述符或者maxevents小于0)?

二、写过程

水平触发(LT):只要写缓冲区还有空间,就返回写就绪。

边缘触发(ET):

? ? 1.首次加入epoll且写缓冲区有空间,返回写就绪(参考四用例第一次调用printf)

? ? 2.写缓冲区内容被取走,返回写就绪(参考四用例的fflush,\n有类似作用)

? ? 3.EPOLL_CTL_MOD修改关联文件描述符event,且写缓冲区有空间,返回写就绪(参考四用例epoll_ctl)

三、读过程

水平触发:只要读缓冲区有数据,就返回可读。

边缘触发:

? ? 数据到来的时候返回可读。(即如果上一次没有读完的数据,需要等到下一次数据到来的时候才能继续读)。

四、用例(写过程)

#include stdio.h

#include sys/epoll.h

#define STDOUT_FILENO 1

int main(void) {

? int epfd, nfds;

? struct epoll_event ev, events[5]; //ev用于注册事件,数组用于返回要处理的事件

? epfd = epoll_create(1); //只需要监听一个描述符——标准输出

? ev.data.fd = STDOUT_FILENO;

? ev.events = EPOLLOUT | EPOLLET; //监听读状态同时设置ET模式

? epoll_ctl(epfd, EPOLL_CTL_ADD, STDOUT_FILENO, ev); //注册epoll事件

? for (;;) {

? ? nfds = epoll_wait(epfd, events, 5, -1);

? ? for (int i = 0; i nfds; i++) {

? ? ? ?if (events[i].data.fd == STDOUT_FILENO) {

? ? ? ? ? ? printf( "hello world!");

// ? ? ? ? ev.data.fd=STDOUT_FILENO;

// ? ? ? ? ev.events=EPOLLOUT|EPOLLET;

// ? ? ? ? epoll_ctl (epfd,EPOLL_CTL_MOD,STDOUT_FILENO,ev); //重新MOD事件(ADD无效),返回写就绪,循环输出

//? ? ? ? ? fflush (stdout); //读取写缓冲区数据,返回写就绪,循环输出

}}}}

五、如何判断客户端关闭连接

1. TCP recv返回0, 说明对方关闭

2. 注册EPOLLERR, 收到事件是关闭

3. recv/send 返回-1时, 如果错误不是EWOULDBLOCK或者EINTR, 也主动关闭连接。

19. fopen、fclose、feof、fputc、fgetc、fread、fwrite、ftell、fseek函数的用法。

clearerr(清除文件流的错误旗标)

相关函数 feof

表头文件 #includestdio.h

定义函数 void clearerr(FILE * stream);

函数说明 clearerr()清除参数stream指定的文件流所使用的错误旗标。

返回值

fclose(关闭文件)

相关函数 close,fflush,fopen,setbuf

表头文件 #includestdio.h

定义函数 int fclose(FILE * stream);

函数说明 fclose()用来关闭先前fopen()打开的文件。此动作会让缓冲区内的数据写入文件中,并释放系统所提供的文件资源。

返回值 若关文件动作成功则返回0,有错误发生时则返回EOF并把错误代码存到errno。

错误代码 EBADF表示参数stream非已打开的文件。

范例 请参考fopen()。

fdopen(将文件描述词转为文件指针)

相关函数 fopen,open,fclose

表头文件 #includestdio.h

定义函数 FILE * fdopen(int fildes,const char * mode);

函数说明 fdopen()会将参数fildes 的文件描述词,转换为对应的文件指针后返回。参数mode 字符串则代表着文件指针的流形态,此形态必须和原先文件描述词读写模式相同。关于mode 字符串格式请参考fopen()。

返回值 转换成功时返回指向该流的文件指针。失败则返回NULL,并把错误代码存在errno中。

范例 #includestdio.h

main()

{

FILE * fp =fdopen(0,”w+”);

fprintf(fp,”%s\n”,”hello!”);

fclose(fp);

}

执行 hello!

feof(检查文件流是否读到了文件尾)

相关函数 fopen,fgetc,fgets,fread

表头文件 #includestdio.h

定义函数 int feof(FILE * stream);

函数说明 feof()用来侦测是否读取到了文件尾,尾数stream为fopen()所返回之文件指针。如果已到文件尾则返回非零值,其他情况返回0。

返回值 返回非零值代表已到达文件尾。

fflush(更新缓冲区)

相关函数 write,fopen,fclose,setbuf

表头文件 #includestdio.h

定义函数 int fflush(FILE* stream);

函数说明 fflush()会强迫将缓冲区内的数据写回参数stream指定的文件中。如果参数stream为NULL,fflush()会将所有打开的文件数据更新。

返回值 成功返回0,失败返回EOF,错误代码存于errno中。

错误代码 EBADF 参数stream 指定的文件未被打开,或打开状态为只读。其它错误代码参考write()。

fgetc(由文件中读取一个字符)

相关函数 open,fread,fscanf,getc

表头文件 includestdio.h

定义函数 nt fgetc(FILE * stream);

函数说明 fgetc()从参数stream所指的文件中读取一个字符。若读到文件尾而无数据时便返回EOF。

返回值 getc()会返回读取到的字符,若返回EOF则表示到了文件尾。

范例 #includestdio.h

main()

{

FILE *fp;

int c;

fp=fopen(“exist”,”r”);

while((c=fgetc(fp))!=EOF)

printf(“%c”,c);

fclose(fp);

}

fgets(由文件中读取一字符串)

相关函数 open,fread,fscanf,getc

表头文件 includestdio.h

定义函数 har * fgets(char * s,int size,FILE * stream);

函数说明 fgets()用来从参数stream所指的文件内读入字符并存到参数s所指的内存空间,直到出现换行字符、读到文件尾或是已读了size-1个字符为止,最后会加上NULL作为字符串结束。

返回值 gets()若成功则返回s指针,返回NULL则表示有错误发生。

范例 #includestdio.h

main()

{

char s[80];

fputs(fgets(s,80,stdin),stdout);

}

执行 this is a test /*输入*/

this is a test /*输出*/

fileno(返回文件流所使用的文件描述词)

相关函数 open,fopen

表头文件 #includestdio.h

定义函数 int fileno(FILE * stream);

函数说明 fileno()用来取得参数stream指定的文件流所使用的文件描述词。

返回值 返回文件描述词。

范例 #includestdio.h

main()

{

FILE * fp;

int fd;

fp=fopen(“/etc/passwd”,”r”);

fd=fileno(fp);

printf(“fd=%d\n”,fd);

fclose(fp);

}

执行 fd=3

fopen(打开文件)

相关函数 open,fclose

表头文件 #includestdio.h

定义函数 FILE * fopen(const char * path,const char * mode);

函数说明 参数path字符串包含欲打开的文件路径及文件名,参数mode字符串则代表着流形态。

mode有下列几种形态字符串:

r 打开只读文件,该文件必须存在。

r+ 打开可读写的文件,该文件必须存在。

w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。

w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。

a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。

a+ 以附加方式打开可读写的文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。

上述的形态字符串都可以再加一个b字符,如rb、w+b或ab+等组合,加入b 字符用来告诉函数库打开的文件为二进制文件,而非纯文字文件。不过在POSIX系统,包含Linux都会忽略该字符。由fopen()所建立的新文件会具有S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH(0666)权限,此文件权限也会参考umask 值。

返回值 文件顺利打开后,指向该流的文件指针就会被返回。若果文件打开失败则返回NULL,并把错误代码存在errno 中。

附加说明 一般而言,开文件后会作一些文件读取或写入的动作,若开文件失败,接下来的读写动作也无法顺利进行,所以在fopen()后请作错误判断及处理。

范例 #includestdio.h

main()

{

FILE * fp;

fp=fopen(“noexist”,”a+”);

if(fp= =NULL) return;

fclose(fp);

}

fputc(将一指定字符写入文件流中)

相关函数 fopen,fwrite,fscanf,putc

表头文件 #includestdio.h

定义函数 int fputc(int c,FILE * stream);

函数说明 fputc 会将参数c 转为unsigned char 后写入参数stream 指定的文件中。

返回值 fputc()会返回写入成功的字符,即参数c。若返回EOF则代表写入失败。

范例 #includestdio.h

main()

{

FILE * fp;

char a[26]=”abcdefghijklmnopqrstuvwxyz”;

int i;

fp= fopen(“noexist”,”w”);

for(i=0;i26;i++)

fputc(a[i],fp);

fclose(fp);

}

fputs(将一指定的字符串写入文件内)

相关函数 fopen,fwrite,fscanf,fputc,putc

表头文件 #includestdio.h

定义函数 int fputs(const char * s,FILE * stream);

函数说明 fputs()用来将参数s所指的字符串写入到参数stream所指的文件内。

返回值 若成功则返回写出的字符个数,返回EOF则表示有错误发生。

范例 请参考fgets()。

fread(从文件流读取数据)

相关函数 fopen,fwrite,fseek,fscanf

表头文件 #includestdio.h

定义函数 size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream);

函数说明 fread()用来从文件流中读取数据。参数stream为已打开的文件指针,参数ptr 指向欲存放读取进来的数据空间,读取的字符数以参数size*nmemb来决定。Fread()会返回实际读取到的nmemb数目,如果此值比参数 nmemb 来得小,则代表可能读到了文件尾或有错误发生,这时必须用feof()或ferror()来决定发生什么情况。

返回值 返回实际读取到的nmemb数目。

附加说明

范例 #includestdio.h

#define nmemb 3

struct test

{

char name[20];

int size;

}s[nmemb];

main()

{

FILE * stream;

int i;

stream = fopen(“/tmp/fwrite”,”r”);

fread(s,sizeof(struct test),nmemb,stream);

fclose(stream);

for(i=0;inmemb;i++)

printf(“name[%d]=%-20s:size[%d]=%d\n”,i,s[i].name,i,s[i].size);

}

执行 name[0]=Linux! size[0]=6

name[1]=FreeBSD! size[1]=8

name[2]=Windows2000 size[2]=11

freopen(打开文件)

相关函数 fopen,fclose

表头文件 #includestdio.h

定义函数 FILE * freopen(const char * path,const char * mode,FILE * stream);

函数说明 参数path字符串包含欲打开的文件路径及文件名,参数mode请参考fopen()说明。参数stream为已打开的文件指针。Freopen()会将原stream所打开的文件流关闭,然后打开参数path的文件。

返回值 文件顺利打开后,指向该流的文件指针就会被返回。如果文件打开失败则返回NULL,并把错误代码存在errno 中。

范例 #includestdio.h

main()

{

FILE * fp;

fp=fopen(“/etc/passwd”,”r”);

fp=freopen(“/etc/group”,”r”,fp);

fclose(fp);

}

fseek(移动文件流的读写位置)

相关函数 rewind,ftell,fgetpos,fsetpos,lseek

表头文件 #includestdio.h

定义函数 int fseek(FILE * stream,long offset,int whence);

函数说明 fseek()用来移动文件流的读写位置。参数stream为已打开的文件指针,参数offset为根据参数whence来移动读写位置的位移数。

参数 whence为下列其中一种:

SEEK_SET从距文件开头offset位移量为新的读写位置。SEEK_CUR 以目前的读写位置往后增加offset个位移量。

SEEK_END将读写位置指向文件尾后再增加offset个位移量。

当whence值为SEEK_CUR 或SEEK_END时,参数offset允许负值的出现。

下列是较特别的使用方式:

1) 欲将读写位置移动到文件开头时:fseek(FILE *stream,0,SEEK_SET);

2) 欲将读写位置移动到文件尾时:fseek(FILE *stream,0,0SEEK_END);

返回值 当调用成功时则返回0,若有错误则返回-1,errno会存放错误代码。

附加说明 fseek()不像lseek()会返回读写位置,因此必须使用ftell()来取得目前读写的位置。

范例 #includestdio.h

main()

{

FILE * stream;

long offset;

fpos_t pos;

stream=fopen(“/etc/passwd”,”r”);

fseek(stream,5,SEEK_SET);

printf(“offset=%d\n”,ftell(stream));

rewind(stream);

fgetpos(stream,pos);

printf(“offset=%d\n”,pos);

pos=10;

fsetpos(stream,pos);

printf(“offset = %d\n”,ftell(stream));

fclose(stream);

}

执行 offset = 5

offset =0

offset=10

ftell(取得文件流的读取位置)

相关函数 fseek,rewind,fgetpos,fsetpos

表头文件 #includestdio.h

定义函数 long ftell(FILE * stream);

函数说明 ftell()用来取得文件流目前的读写位置。参数stream为已打开的文件指针。

返回值 当调用成功时则返回目前的读写位置,若有错误则返回-1,errno会存放错误代码。

错误代码 EBADF 参数stream无效或可移动读写位置的文件流。

范例 参考fseek()。

fwrite(将数据写至文件流)

相关函数 fopen,fread,fseek,fscanf

表头文件 #includestdio.h

定义函数 size_t fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream);

函数说明 fwrite()用来将数据写入文件流中。参数stream为已打开的文件指针,参数ptr 指向欲写入的数据地址,总共写入的字符数以参数size*nmemb来决定。Fwrite()会返回实际写入的nmemb数目。

返回值 返回实际写入的nmemb数目。

范例 #includestdio.h

#define set_s (x,y) {strcoy(s[x].name,y);s[x].size=strlen(y);}

#define nmemb 3

struct test

{

char name[20];

int size;

}s[nmemb];

main()

{

FILE * stream;

set_s(0,”Linux!”);

set_s(1,”FreeBSD!”);

set_s(2,”Windows2000.”);

stream=fopen(“/tmp/fwrite”,”w”);

fwrite(s,sizeof(struct test),nmemb,stream);

fclose(stream);

}

执行 参考fread()。

(责任编辑:IT教学网)

更多

推荐Flash实例教程文章