系统函数与基本输入输出系统的关系描述

(window.slotbydup=window.slotbydup || []).push({
id: '2014386',
container: s,
size: '234,60',
display: 'inlay-fix'
(18人评价)
&&|&&1次下载&&|&&总176页&&|
您的计算机尚未安装Flash,点击安装&
阅读已结束,如需下载到电脑,请使用积分()
下载:60积分
0人评价39页
0人评价130页
0人评价189页
0人评价73页
0人评价15页
所需积分:(友情提示:所有文档均可免费全文预览!下载之前请务必先预览阅读,以免误下载造成积分浪费!)
(多个标签用逗号分隔)
文不对题,内容与标题介绍不符
广告内容或内容过于简单
文档乱码或无法正常显示
若此文档涉嫌侵害了您的权利,请参照说明。
评价文档:
下载:60积分描述函数法/描述函数法
正文/描述函数法
   从频率域的角度研究的的一种等效线性化方法。在苏联文献中,常把这种方法称为。描述函数法是把中经典频率域方法应用于非线性系统研究的一种推广,只适用于非线性程度较低的系统。对于非线性程度高的系统,应用描述函数法可能导致错误的结论。在工程技术领域中,许多实际的控制系统都能满足描述函数法的限制条件,因而也都能应用这种方法。    描述函数& 对于一个特性不随时间变化的非线性元件,输入是正弦变化并不保证输出也是正弦变化,但可保证输出必然是一个周期函数,而且其周期与输入信号的周期相同。将输入正弦函数表示为x(t)=Xsin&t,同时把输出周期函数y(t)展开成傅里叶级数 则非线性元件的描述函数规定为,由输出的一次谐波分量对输入正弦函数的振幅之比为模和它们的相位之差为相角组成的一个复函数,其表达式为 式中X是正弦输入的振幅,Y1是输出的一次谐波分量的振幅,φ1是输出的一次谐波分量与正弦输入的相位差。因此,一个非线性元件就可采用由描述函数表征的一个线性元件来等效。这种等效的近似性实质上就是,在使非线性元件与其等效线性元件的输出偏差均方值为极小意义下的最优逼近。描述函数 N与输入正弦函数的角频率&无关,为输入正弦函数振幅X的一个复函数。上表列出一些典型的非线性特性的描述函数。   稳定性分析& 描述函数的一个主要用途是分析非线性控制系统的稳定性,特别是预测系统的自激振荡(周期运动)。对于一类由线性部件和非线性部件构成的(图1),假定其线性部分为并采用 G(j&)表示它的特性,而用描述函数N表示系统中非线性特性的近似等效特性。那么在同一个复数平面上作出G(j&) 当& 由0变化到∞的轨迹和-1/N当X由0变化到∞的轨迹后,就可从这两个轨迹的相互分布关系得到判断此类闭环控制系统的稳定性的一些判据。 描述函数法&描述函数法  ①稳定和不稳定判据 如果-1/N 轨迹没有被G(j&)轨迹所包围,则闭环控制系统是稳定的。而当-1/N 轨迹被 G(j&)轨迹所包围时,闭环控制系统是不稳定的。在前一情况下,系统不会出现自激振荡;在后一情况下,系统输出将增加到安全装置所限定的极限值。   ②自激振荡判据 如果-1/N 轨迹和G(j&)轨迹相交,则闭环系统的输出可能出现自激振荡。这种自激振荡一般不是正弦的,其角频率值和振幅值分别为交点处G(j&)轨迹上的&值和-1/N轨迹上的X 值。但是,并非所有交点都能构成稳定自激振荡。只有-1/N轨迹的进行方向是由 G(j&)的包围区过渡到非包围区的那些交点(如图2的B点)才能构成稳定自激振荡。   控制系统的综合& 描述函数法对于非线性控制系统的综合,也提供了方便的工具。通过引入适当的校正装置可以改变系统线性部分频率响应G(j&)轨迹的形状,从而使闭环控制系统中不出现自激振荡并确保较好的性能。   描述函数法的准确度& 描述函数法在分析非线性控制系统中的有效性和准确度,主要取决于非线性元件输出周期函数中的高次谐波分量在通过线性部分后被衰减的程度。高阶线性系统通常具有较好的低通滤波特性,因此用这个方法分析非线性系统时,线性部分为高阶时的分析准确度往往比线性部分为低阶时好得多。对于判断自激振荡,则当-1/N 轨迹和G(j&)轨迹接近于垂直相交时,描述函数法的分析准确度较高。   参考书目  D.P.Atherton,Nonlinear Control Engineering, Van North and Reinhold, London, 1975.&
配图/描述函数法
相关连接/描述函数法
&|&相关影像
互动百科的词条(含所附图片)系由网友上传,如果涉嫌侵权,请与客服联系,我们将按照法律之相关规定及时进行处理。未经许可,禁止商业网站等复制、抓取本站内容;合理使用者,请注明来源于。
登录后使用互动百科的服务,将会得到个性化的提示和帮助,还有机会和专业认证智愿者沟通。
此词条还可添加&
编辑次数:3次
参与编辑人数:3位
最近更新时间: 16:37:00
贡献光荣榜C/C++技术(1)
&&&&&&& 在Linux和UNIX中有很多的输入输出函数,有时真是让想跟它攀点关系的菜鸟们束手无策。先来看看都有哪些函数,通过解析与总结,看看能不能让大家能这些函数有个理性的认识,哦,原来是这么回事,也就算我没白花这份闲。
内核文件I/O->标准库I/O->高级I/O->IPC中
1.&&&&&&&&&read()/write();
2.&&&&&&&&&pread()/pwrite();
3.&&&&&&&&&getc()/putc();
4.&&&&&&&&&fgetc()/fputc();
5.&&&&&&&&&getchar()/putchar();
6.&&&&&&&&&ferror()/feof();
7.&&&&&&&&&fgets()/fputs();
8.&&&&&&&&&gets()/puts();
9.&&&&&&&&&fread()/fwrite();
10.&&&&&scanf()/fscanf()/sscanf()/vscanf()/vfscanf()/vsscanf()
11.&&&&&printf()/fprintf()/sprintf()/snprintf()/vprintf()/vfprintf()/vsprintf()/vsanprintf()
12.&&&&&readv()/writev()
13.&&&&&read()/written()
14.&&&&&msgrcv()/msgsnd()
15.&&&&&revc()/recvfrom()/recvmsg()
16.&&&&&send()/sendto()/sendmsg()
17.&&&&&recv_fd()/send_fd()/send_err()
&&粗略总结了下,有如上边所示的17个大类,咋一看,的确让人头有点小晕。但是大师们都说存在的就是合理的,下边让我们看看,是怎么样的深入浅出,让这些函数有了存在的理由。要理解这些,先要知道系统在输入输出时所要经过的逻辑处理模块是怎样。如下图示
以上的用户空间的应用程序利用系统调用完成文件的读写过程,说明如下:
(1)&&&&&&&用户空间与内核空间;这一组关系不用说明了。
(2)&&&&&&&读与写:都将cpu或是内存或是用户程序看成主体,则读,内存<-文件;写,内存->文件;因为主体是用户程序,所以在读或是写是,对读,要确定从什么读,对写,向什么写。
(3)&&&&&&&应用程序利用系统服务有三条路:通过shell命令等直接实现;利用库函数实现;直接调用系统调用的函数,如read,write等命令。在这里可以将库函数与系统调用的关系看清楚了。系统调用是最基本的了,任何想要获得系统服务的都要经过它,这是个关卡。
(4)&&&&&&&文件I/O与标准I/O:前者是指在用户空间中不需要其实进程明确提供一个缓冲(如图中的bf2),其实就是进程在用户空间直接调用read/write等函数,但是,在内核空间中都是要有缓冲的。这一般称为文件I/O。标准I/O:提供了一种对不用缓冲I/O的函数(这些函数即可以用于不用缓冲的I/O函数,也可以有于带有缓冲的I/O函数)的带缓冲的接口。这一般是库函数在用户空间建立的(这些缓冲由库函数完成,不需用户自己管理,是封装在库函数中的),如BUF2,可能是库函数想将对从上层接收过来的数据做个预处理,如格式变换等。使用标准I/O函数可以无需担心如何选取最佳的缓冲区大小(由库函数为你完成),还有一个是简化了对输入行的处理。标准I/O函数库提供了使我们能够控制该库使用的缓冲风格的函数。
(5)&&&&&&&BUF1/BUF2/BUF3:BUF1,其实是用户空间的一些字符串,变量等,理解为数据即可。有时也定义为名称BUF的形式,如char buf[MAXLINE];,但此时BUF只是名称叫BUF而矣,区别于真正的缓冲区的概念。BUF2,这是库函数为您老在用户空间建立的,不用您亲自管理,您只要一声令下,如调用个库函数中某个函数,自有人为你服务,这个BUF2,我们称之为真正的缓冲区。BUF3,不论您是选择文件I/O的形式还是标准I/O的形式,不论是哪一种,在内核中的都要用到缓冲区BUF3(这是怎么样都免不了的),但是这个也不要用户来亲力亲为,由内核代为管理。
(6)&&&&&&&流(stream):这是标准为I/O中用到的,流是文件的逻辑代表,将文件I/O的:    进程->fd->文件,改变为:进程->fp(FILE对象)->流/缓冲->文件。原来对文件的操作,现在用户只用处理:进程->流之间的操作,而流->文件之间的操作将由库函数为你完成。流的逻辑表示就是FILE对象,而流的实体就是流使用的缓冲区,这些缓冲区相对于应用进程来说就是文件的代表。流=FILE + 缓冲。标准I/O库提供缓冲的的是尽可能减少使用read&和write的次数。
好,暂此做以上四点说明吧,待有想法时再添加。下边进入正题,看看上边的这些函数,是什么形式的,为什么要有这些函数的存在,都为系统做些什么,怎么做的。
1.&&&&&&&文件I/O相关(进程->fd->文件)(文件fd, buf):
(1)&&&&&&&read()
形式:#include&unistd.h&
&&&&&&ssize_t&&read (int filedes,&&void *buf,&&size_t&&nbytes );
&&&&&&成功:返回读到的字节数;出错:返回-1;文件尾:返回0;
原因:基本系统调用功能;
实现:文件(由filedes所指)-读nbytes字节->内存buf中。
补充:有多种情况可使实际读到的字节数少于要求读的字节数:
当从普通文件读时,在读到要求字节数之前已到达了文件尾端。
当从终端设备读时,通常一次最多读一行。
当从网络读时,网络中缓冲机构可能造成返回值小于所要求读的字节数。
当从管道或FIFO读时,如若管道包含的字节少于所需的数量,那么只返回实际用
的字节数。
当从某些面向记录的设备读时,一次最多返回一个记录。
当某一信号造成中断,而已经读了部分数据量时。
读操作从文件的当前偏移量处开始,在成功返回之前,该偏移量将增加实际读到的字节数。常用的unix系统shell都提供一种方法,它在标准输入上打开一个文件,在标准输出上追寻或重写一个文件,这使得程序不必自行打开输入和输出文件。
(2)&&&&&&&write()
形式:#include&unistd.h&
&&&&&&ssize_t&&write (int filedes,&&const void *buf,&&size_t&&nbytes );
&&&&&&成功:返回已写的字节数;出错:返回-1;
原因:基本系统调用功能;
实现:文件(由filedes所指)<-写nbytes字节-内存buf中。
补充:write出错的一个常见的原因是:磁盘已写满,或者超过了一个给定进程的文件长度限制。对于普通文件,写操作从文件的当前偏移量处开始。如果在打开该文件时,指定了O_APPEND选项,则在每次写操作之前,将文件偏移量设置在文件的当前结尾处。在一次成功写之后,该文件偏移量增加实际写的字节数。
(3)&&&&&&&pread()
形式:#include&unistd.h&
&&&&&&ssize_t&&pread (int filedes,&&&void *buf,&&size_t&&nbytes,&&off_t&&offset );
&&成功:返回读到的字节数;出错:返回-1;到文件结尾:返回0
原因:由于lseek和read&调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pread相当于顺序调用了lseek&和 read,这两个操作相当于一个捆绑的原子操作。
实现:文件(由filedes所指)-读nbytes字节->内存buf中。
补充:调用pread时,无法中断其定位和读操作,另外不更新文件指针。
(4)&&&&&&&pwrite()
形式:#include&unistd.h&
&&&&&&ssize_t&&pwrite (int filedes,&&&const void *buf,&&size_t&&nbytes,&&off_t&&offset );
&&成功:返回已写的字节数;出错:返回-1;
原因:由于lseek和write&调用之间,内核可能会临时挂起进程,所以对同步问题造成了问题,调用pwrite相当于顺序调用了lseek&和 write,这两个操作相当于一个捆绑的原子操作。
实现:文件(由filedes所指)<-写nbytes字节-内存buf中。
补充:调用pwrite时,无法中断其定位和读操作,另外不更新文件指针。
2.&&&&&&&流(stream)或标准I/O( 进程->fp->流(FILE+缓冲)->文件)(内存buf,&流fp):
每次输入一个字符:
(1)&&&&&&&getc();
格式:#include &stdio.h&
&&&&&&int getc(FILE *fp);
&&&&&&成功:返回下一个字符;出错:返回EOF;文件尾:EOF;
实现:内存 <-读一个字符c- 流(由fp所指的流,是文件的逻辑代表)
原因:在标准I/O中用,将流看成文件的逻辑代表,将对进程->文件的操作,现转换为进程->流(也就是相当于文件)的操作。
补充:函数在返回下一个字符时,会将其unsigned char类型转换为int类型。为不带符号的理由是,如果最高位是1也不会使返回值为负。要求整形返回值的理由是,这样就可以返回所有可能的字符值再加上一个已出错或已到达文件尾端的指示值。即字符值变为正的int值,负的值就是出错或是到达文件尾端。(负值表特殊意义),同时不论是出错还是到达文件尾端,这三个函数都返回同样的值即都是-1。由于每个流在FILE对象中维持了两个标志,即出错标志和文件结束标志,为了区分其不同,必须调用ferror或feof。
(2)&&&&&&&fgetc();
格式:#include &stdio.h&
&&&&&&int fgetc(FILE *fp);
&&&&&&成功:返回下一个字符;出错:返回EOF;文件尾:EOF;
实现:同getc
原因:同getc
补充:同getc
(3)&&&&&&&getchar();
格式:#include &stdio.h&
&&&&&&int getchar(void);
成功:返回下一个字符;出错:返回EOF;文件尾:EOF;
实现:内存 <-读一个字符c- 流(由stdin所指的流,是标准输入文件的逻辑代表),所以getchar=getc(stdin);
原因:同getc
补充:同getc
每次输入一行:
(4)&&&&&&&fgets();
格式:#include &stdio.h&
&&&&&&char *fgets(char *restrict buf,&&Int n,&&FILE *restrict&&fp);
&&&&&&成功:返回buf;出错:返回NULL;&文件结尾:NULL;
实现:内存buf <-从fp所指的流中取一行字符- 流(由fp所指)
原因:在标准I/O中用,将流看成文件的逻辑代表,将对进程->文件的操作,现转换为进程->流(也就是相当于文件)的操作。
补充:必须指定用户进程缓冲区的长度n,即buf的大小,此函数从流中一直读到下一个换行符为止,但是不超过n-1个字符,读入的字符被送入用户缓冲区buf中。该缓冲区以null字符结尾。如若该行包括最后换行符的字数大于n-1,则其只返回一个不完整的行,但是缓冲区buf总是以null字符结尾,对此函数的调用会继续读该行。缓冲区buf中的内容为:(字符+换行符)+null。所以字符+换行符<=n-1,因为一定要留一个NULL字符来标识缓冲区的结束;
(5)&&&&&&&gets();
格式:#include &stdio.h&
&&&&&&char *gets(char * buf);
&&&&&&成功:返回buf;出错:返回NULL;&文件结尾:NULL;
实现:内存buf <-从stdin所指的流中取1行字符-标准输入流(由fp=stdin所指)
原因:同上;
补充:不推荐使用,问题是调用者在使用gets时,不能指定缓冲区buf(用户进程)的长度,这样可能造成缓冲区溢出。
每次输出一个字符:
(6)&&&&&&&putc();
格式:#include &stdio.h&
&&&&&&int putc(int c ,FILE *fp);
&&&&&&成功:返回c;出错:返回EOF;
实现:内存中整形变量c-写字符C->流(由fp所指)。至于流什么时候将C写入文件中,这个由库函数来实现,不用用户操心;
(7)&&&&&&&fputc();
格式:#include &stdio.h&
&&&&&&int fputc(int c ,FILE *fp);
&&&&&&成功:返回c;出错:返回EOF;
实现:内存中整形变量c-写字符C->流(由fp所指)。至于流什么时候将C写入文件中,这个由库函数来实现,不用用户操心;
(8)&&&&&&&putchar();
格式:#include &stdio.h&
&&&&&&int putchar(int c);
&&&&&&成功:返回c;出错:返回EOF;
实现:内存中整形变量c-写字符C->流(由fp=stdout所指)。至于流什么时候将C写入标准输出文件中,这个由库函数来实现,不用用户操心;
补充:putchar(c)=putc(c,stdout);
每次输出一行:
(9)&&&&&&&fputs();
格式:#include &stdio.h&
&&&&&&int fputs(const char *restrict&&str, FILE&&*restrict&&fp);
   成功:返回非负值;出错:返回EOF;
实现:内存中字符数组str-写字符数组str->流(由fp所指)。
补充:将一个以null符终止的字符串(相当于用户空间buf,肯定有null,对应于fgets的buf中一定要有个null来标识缓冲区buf的结束。)写到指定的流,尾端的终止符null不写进流中。注意,这并不一定是每次输出一行,因为它并不要求在null之前一定是换行符,buf中有就有,没有就没有,通常,在空字符之前是一个换行符,但并不要求总是如此。用户空间buf:字符(+换行符)+null;流中的buf:字符+换行符。
(10)&&&puts();
格式:#include &stdio.h&
&&&&&&int puts(const char * str);
   成功:返回非负值;出错:返回EOF;
实现:内存中字符数组str-写字符数组str->标准输出流(由fp=stdout所指)。
补充:将一个以null结尾的字符串写到标准输出上,相当于进程->流->标准输出文件。终止符不写出,但是puts然后又将一个换行符写到标准输出。应当少用,以免需要记住它在最后是否添加了一个换行符。而fgets和fputs在处理换行符,本着实事求是的态度,有就有,没有就没有,不会在用户buf和流缓冲以及文件中自己添加,只是在数据经过流缓冲时,增加或是过滤到null字符。当fgets时会在用户buf中增加一个null以标识用户buf的结束,而fputs时,以null为终止字符,但是尾端的null并不写在流中。
二进制I/O:
(11)&&&fread()
格式:#include &stdio.h&
&&&&&&ssize_t&&fread(void *restrict ptr, size_t size, size_t nobj, FILE *restrict&&fp);
&&&&&&成功:读到的对象数。
实现:内存始址ptr<-读N个对象- 流(由fp所指)
原因:以上有一次一个字符或是一次一行的方式进行I/O操作,当我们读或写一个结构时,对于一次一个字符的方式,必须循环通过整个结构,每次循环处理一个字节,一次读或写一个字节,这会很烦。而对于一次一行的方式,当每次结构体中有null字符时,fputs就会停止,所以也不能用它实现读结构,同时fgets中包含有null字节或换行符,其也不能正常工作。所以要并实现结构体作为一个整体的读或写。
补充:使用二进制的基本问题是:它只能用于读在同一系统上已写的数据。其原
因是:在结构中,同一成员偏移量可能因为编译器和系统而异,另外,用来存储多字节整数和浮点值的二进制格式在不同的机器体系结构之间也可能不同。
(12)&&&fwrite()
格式:#include &stdio.h&
&&&&&&ssize_t&&fwrite(const void *restrict ptr, size_t size, size_t nobj, FILE *restrict&&fp);
&&&&&&成功:写的对象数。
实现:内存始址ptr-写N个对象-> 流(由fp所指)
格式化输入:文件-流->格式转换->内存变量中
(13)&&&scanf();
格式:#include &stdio.h&
&&&&&&int scanf(const char *restrict format,…)
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:标准输入流->格式转换->内存变量中。用于分析输入字符串,并将字符序列转换成指定类型的变量。格式之后的各个参数包含了变量的地址,以用转换结果初始化这些变量。
原因:要在流中做格式转换,再将结果放到内存变量中
(14)&&&fscanf();
格式:#include &stdio.h&
&&&&&&int fscanf(FILE *restrict fp, const char *restrict format,…)
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:输入流->格式转换->内存变量中
(15)&&&sscanf();
格式:#include &stdio.h&
&&&&&&int sscanf(const char *restrict buf, const char *restrict format,…)
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:内存buf->格式转换->内存变量中。
补充:对于scanf(),&从标准输入流中输入;fscanf,从流中输入;&sscanf,这个比较特殊,不是从流中输入,而是内存的一个buf相当于string中输入。
(16)&&&vscanf();
格式:#include &stdio.h&
&&&&&&int vscanf(const char *restrict format, va_list&&arg);
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:标准输入流->格式转换->内存变量中。用于分析输入字符串,并将字符序列转换成指定类型的变量。格式之后的各个参数包含了变量的地址,以用转换结果初始化这些变量。同于scanf,只是将原来的可变参数…换成了
原因:要在流中做格式转换,再将结果放到内存变量中
(17)&&&vfscanf();
格式:#include &stdio.h&
&&&&&&int vfscanf(FILE *restrict fp, const char *restrict format, va_list&&arg)
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:输入流->格式转换->内存变量中,&同于fscanf,只是将原来的可变参数…,换成了
(18)&&&vsscanf();
格式:#include &stdio.h&
&&&&&&int vsscanf(const char *restrict buf, const char *restrict format, va_list&&arg)
   成功:指定的输入项数;出错:返回EOF;输入出错或在任意变换前已到达文件结尾:EOF;
实现:内存buf->格式转换->内存变量中。同于sscanf,只是将原来的可变参数…,换成了
补充:对于scanf(),&从标准输入流中输入;fscanf,从流中输入;&sscanf,这个比较特殊,不是从流中输入,而是内存的一个buf相当于string中输入。
格式化输出:文件-流<-格式字符串<-内存变量
(19)&&&printf();
格式:#include &stdio.h&
&&&&&&int&&printf(const char *restrict format, …);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:标准输出流<-格式字符串<-内存变量
原因:要将内存变量的数据做格式变换,再将变换的结果放入流中
(20)&&&fprintf();
格式:#include &stdio.h&
&&&&&&int&&fprintf(FILE *restrict fp,const char *restrict format, …);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:文件-输出流<-格式字符串<-内存变量
(21)&&&sprint();
格式:#include &stdio.h&
&&&&&&int&&sprintf(char *restrict buf, const char *restrict format, …);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:内存字符串buf<-格式字符串<-内存变量,就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。
(22)&&&snprintf();
格式:#include &stdio.h&
&&&&&&int&&snprintf(char *restrict buf, size_t n , const char *restrict format, …);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:内存字符串buf<-格式字符串<-内存变量,就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。只能输入n-1个字符,超过的任何字条都会被丢弃。
(23)&&&vprintf();
格式:#include &stdarg.h&
&&&&&&#include &stdio.h&
&&&&&&int&&vprintf(const char *restrict format, va_list&&arg);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:标准输出流<-格式字符串<-内存变量,同于printf,只是将原来的可变参数…换成了
原因:要将内存变量的数据做格式变换,再将变换的结果放入流中
(24)&&&vfprintf();
格式:#include &stdarg.h&
&&&&&&#include &stdio.h&
&&&&&&int&&vfprintf(FILE *restrict fp,const char *restrict format, va_list&&arg);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:输出流<-格式字符串<-内存变量,同于fprintf,只是将原来的可变参数…换成了
原因:要将内存变量的数据做格式变换,再将变换的结果放入流中
(25)&&&vsprintf();
格式:#include &stdarg.h&
&&&&&&#include &stdio.h&
&&&&&&int&&vsprintf(char *restrict buf, const char *restrict format, va_list&&arg);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:内存数组buf<-格式字符串<-内存变量,同于sprintf,只是将原来的可变参数…换成了&就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。
原因:要将内存变量的数据做格式变换,再将变换的结果放入流中
(26)&&&vsnprintf();
格式:#include &stdio.h&
&&&&&&int&&vsnprintf(char *restrict buf, size_t n , const char *restrict format, va_list arg);
&&&&&&成功:返回输出字符数;出错:返回负值;
实现:内存字符串buf<-格式字符串<-内存变量,&同于snprintf,只是将原来的可变参数…换成了&就是将格式化的字符串送入数组buf而不是指定的流中。在数组的尾端自动加一个null字节,但该字节不包括在返回值中。只能输入n-1个字符,超过的任何字条都会被丢弃。
3.&&&&&&&高级I/O:(文件(fd),&内存buf )
(1)&&&&&&&readv()
格式:#include &sys/uio.h&
&&&&&&ssize_t&&readv(int filedes, const&&struct iovec *iov, int iovcnt);
&&&&&&成功:返回已读的字节数;出错:返回-1;
实现:文件(fd)->内存向量中
原因:在一次函数调用中读、写多个非连续缓冲区,但是这些缓冲区已经用iovec表示好了。减少了系统调用的次数。
(2)&&&&&&&writev()
格式:#include &sys/uio.h&
&&&&&&ssize_t&&writev(int filedes, const&&struct iovec *iov, int iovcnt);
&&&&&&成功:返回已读的字节数;出错:返回-1;
实现:文件(fd)&-内存向量
原因:在一次函数调用中读、写多个非连续缓冲区,但是这些缓冲区已经用iovec表示好了。减少了系统调用的次数。
(3)&&&&&&&readn()
格式:#include &sys/uio.h&
&&&&&&ssize_t&&readn(int filedes, void *bug, size_t&&nbytes);
&&&&&&成功:返回已读的字节数;出错:返回-1;
实现:文件(fd)->内存buf中
原因:管道、FIFO以及某些设备,特别是终端、网络和STREAMS设备有下列两种性质:一是,一次read操作所返回的数据可能少于所要求的数据,即使还没达到文件尾端也可能是这样的。这不是一个错误,应当继续读该设备。二是,一次write操作所返回的值也可能少于所指定输出的字节数,这可能是由若干因素造成的。这些也不是错误,也应当继续写余下的数据至该设备。通常只对非阻塞描述符,或捕捉到一个信号时,才发生这种write的中途返回。但是在读写磁盘时,很少遇到这样的情况。所以这个函数其实是按需要多次调用read&和write直至读、写了N个字节数据,即我们称之为:直到集齐了再返回。
(4)&&&&&&&written()
格式:#include &sys/uio.h&
&&&&&&ssize_t&&writen(int filedes, void *bug, size_t&&nbytes);
&&&&&&成功:返回已读的字节数;出错:返回-1;
实现:文件(fd)&-内存buf中
原因:管道、FIFO以及某些设备,特别是终端、网络和STREAMS设备有下列两种性质:一是,一次read操作所返回的数据可能少于所要求的数据,即使还没达到文件尾端也可能是这样的。这不是一个错误,应当继续读该设备。二是,一次write操作所返回的值也可能少于所指定输出的字节数,这可能是由若干因素造成的。这些也不是错误,也应当继续写余下的数据至该设备。通常只对非阻塞描述符,或捕捉到一个信号时,才发生这种write的中途返回。但是在读写磁盘时,很少遇到这样的情况。所以这个函数其实是按需要多次调用read&和write直至读、写了N个字节数据,即我们称之为:直到集齐了再返回。
4.&&&&&&&IPC中:
消息队列中:
(1)&&&&&&&msgrcv()
格式:#include &sys/msg.h&
&&&&&&ssize_t&&msgrcv(int&&msqid, void *ptr, size_t nbytes, long type, int flag);
&&&&&&成功:返回消息的数据部分长度;出错:-1;
实现:消息队列->内存消息结构体(由ptr指向)
补充:nbytes说明数据缓冲区的长度。用来构造mymesg。若返回的消息大于nbytes,而且在flag中设置了MSG_NOERROR,则该消息被截短。如果没有设置这一标志,而消息又太长,则出错返回E2BIG(消息仍留在队列中。参数type我们可以指定想要哪一种消息。可以指定flag值为IPC_NOWAIT,使操作不阻塞。这使得如果没有所指定类型的消息,则msgrcv返回-1,errno设置为ENOMSG。
(2)&&&&&&&msgsnd()
格式:#include &sys/msg.h&
&&&&&&int&&msgsnd(int&&msqid, const void *ptr, size_t nbytes, long type, int flag);
&&&&&&成功:返回0;出错:-1;
实现:消息队列&-内存消息结构体(由ptr指向)
补充:每个消息都由三部分组成,它们是:正长整型类型字段、实际数据字节(这两个对就myseq结构体)、非负长度(nbytes)。消息总是放在队列尾端。ptr参数指向一个长整型数,它包含了正的整型消息类型,在其后紧跟着消息数据。可以定义如下结构:struct myseq{ char mtex[512];}&&于是ptr就是一个指向mymesg结构的指针。接收者可以用消息类型以非先进先出的次序取消息。
SOCKET中:
(1)&&&&&&&revc()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&recv(int sockfd, void *buf, size_t&&nbytes, int flags);
&&&&&&成功:以字节计数的消息长度;出错:-1;无可用消息或对方已经按序结束:0;
实现:网络sockfd-取消息msg->内存buf中。
(2)&&&&&&&recvfrom()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&recvfrom( int sockfd, void *restrict&&buf, size_t&&len, int flags, struct sockaddr *restrict addr, socklen_t *restrict&&addrlen);
&&&&&&成功:以字节计数的消息长度;出错:-1;无可用消息或对方已经按序结束:0;
实现:网络sockfd-取消息msg->内存buf中。
补充:如果addr非空,它将包含数据发送者的套接字端点地址,当调用recvfrom时,需要设置addrlen参数指向一个包含addr所指的套接字缓冲区字节大小的整数。返回时,该整数设为该地址的实际字节大小。因为可以获得发送者的地址,recvfrom通常用于无连接套接字。
(3)&&&&&&&recvmsg()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&recvmsg( int sockfd, struct msghdr *msg, int flags);
&&&&&&成功:以字节计数的消息长度;出错:-1;无可用消息或对方已经按序结束:0;
实现:网络sockfd-取消息msg->内存buf中。
补充:结构msghdr被recvmsg用于指定接收数据的输入缓冲区。
(4)&&&&&&&send()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&send(int sockfd, const&&void *buf, size_t&&nbytes, int flags);
&&&&&&成功:返回发送的字节数;出错:-1;
实现:网络sockfd<-取消息msg-内存buf中。
补充:如果send成功,并不必然表示连接另一端的进程接收数据。所保证的仅是当send成功返回时,数据已经无错误的发送到网络上。
(5)&&&&&&&sendto()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&sendto( int sockfd, const void *restrict&&buf, size_t nbytes, int flags,&&const struct sockaddr *dest addr, socklen_t * addrlen);
成功:返回发送的字节数;出错:-1;
实现:网络sockfd<-取消息msg-内存buf中。
补充:适用于无连接的套接字,不能使用send,除非调用connect时预先设定了目标地址,或者采用了sendto来提供另外一种报文发送方式。
(6)&&&&&&&sendmsg()
格式:#include &sys/socket.h&
&&&&&&ssize_t&&sendmsg( int sockfd,&&const struct msghdr *msg, int flags);
成功:返回发送的字节数;出错:-1;
实现:网络sockfd<-取消息msg-内存buf中。
补充:可以调用带有msghdr结构的sendmsg来指定多重缓冲区传输数据,和writev很像。
传送文件描述符(略,自行实现)
(1)&&&&&&&recv_fd()
(2)&&&&&&&send_fd()
(3)&&&&&&&send_err()
总算整差不多了,虽然花了点时间,但是希望能对大家有帮助,最后谢谢阅读!
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:16970次
排名:千里之外
原创:19篇
(1)(1)(1)(3)(2)(1)(5)(10)

我要回帖

更多关于 系统输入输出设计实例 的文章

 

随机推荐