信息安全系统设计基础第九周学习总结

理解I/O代码

读和写文件

include <unistd.h>

ssize_t read(int fd, void *buf, size_t n);
ssize_t write(int fd, const void *buf, size_t n);

RIO的无缓冲的输入输出函数

include "csapp.h"

void rio_readinitb(rio_t *rp, int fd);//将描述符fd和地址rp处的一个类型为rio_t的读缓存区联系起来。
ssize_t rio_readlineb(rio_t *rp,void *usrbuf, size_t maxlen);//从文件rp中读出一个文本行,包括换行符,拷贝到存储器位置usrbuf,并用空字符结束这个文本行。最多赌到maxlen-1个字节,最后一个给结尾的空字符。
ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n);//从文件rp中读取最多n个字符到存储器位置usrbuf中

RIO的带缓冲的输入函数

图10-4

include "csapp.h"

int main(int argc, char **argv)
{
int n;
rio_t rio;
char buf[MAXLINE];

Rio_readinitb(&rio, STDIN_FILENO);//连接标准输入和rio地址
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) //当成功返回时,将rio中的内容拷贝到存储器位置buf中,最多读maxline-1
Rio_writen(STDOUT_FILENO, buf, n);//把存储器位置中的数据拷贝到标注输出中。
exit(0);

}

内部的rio_read函数

图10-5

static ssize_t rio_read(rio_t *rp, char *usrbuf, size_t n)
{
int cnt;

while (rp->rio_cnt <= 0) {  /* 如果缓存区为空,调用read填满它 */
rp->rio_cnt = read(rp->rio_fd, rp->rio_buf, 
		   sizeof(rp->rio_buf));
if (rp->rio_cnt < 0) {
    if (errno != EINTR) /* 出错返回-1*/
	return -1;
}
else if (rp->rio_cnt == 0)  /* EOF返回0 */
    return 0;
else 
    rp->rio_bufptr = rp->rio_buf; /* reset buffer ptr */
}

/* 一旦缓存区非空,就从读缓存区拷贝n和rp->rio_cnt中较小值个字节到用户缓存区,并且返回拷贝的字节数 */
cnt = n;          
if (rp->rio_cnt < n)   
cnt = rp->rio_cnt;
memcpy(usrbuf, rp->rio_bufptr, cnt);
rp->rio_bufptr += cnt;
rp->rio_cnt -= cnt;
return cnt;

}

rio_readlineb函数

ssize_t rio_readlineb(rio_t *rp, void *usrbuf, size_t maxlen)
{
int n, rc;
char c, *bufp = usrbuf;

for (n = 1; n < maxlen; n++) { //最多是maxlen-1个
if ((rc = rio_read(rp, &c, 1)) == 1) {
    *bufp++ = c;
    if (c == '\n')//找到换行符,就退出
	break;
} else if (rc == 0) {
    if (n == 1)
	return 0; /* EOF,并且没有读到数据 */
    else
	break;    /* EOF,有数据,出现不足值 */
} else
    return -1;	  /* 错误,返回-1 */
}
*bufp = 0;
return n;//返回成功传送的字节数

}

rio_readnb函数

ssize_t rio_readnb(rio_t *rp, void *usrbuf, size_t n)
{
size_t nleft = n;
ssize_t nread;
char *bufp = usrbuf;

while (nleft > 0) {
if ((nread = rio_read(rp, bufp, nleft)) < 0) {
    if (errno == EINTR) 
	nread = 0;      /* 调用read填充 */
    else
	return -1;      /* 错误,返回-1 */ 
} 
else if (nread == 0)
    break;              /* EOF */
nleft -= nread;
bufp += nread;
}
return (n - nleft);         /* 返回成功传送的字节数*/

}

查询和处理一个文件的st_mode位

include "csapp.h"

int main (int argc, char **argv)
{
struct stat stat;
char *type, *readok;

Stat(argv[1], &stat);//文件选择argv[1],写入一个stat数据结构
if (S_ISREG(stat.st_mode))     /* 如果是一个文本文件 */
type = "regular";
else if (S_ISDIR(stat.st_mode))//如果是一个目录文件
type = "directory";
else 
type = "other";
if ((stat.st_mode & S_IRUSR)) /* 检查阅读权限 */
readok = "yes";
else
readok = "no";

printf("type: %s, read: %s\n", type, readok);
exit(0);

}

报告错误函数

void unix_error(char msg) / unix-style error /
{
fprintf(stderr, "%s: %s\n", msg, strerror(errno));
exit(0);
}
/
$end unixerror */

void posix_error(int code, char msg) / posix-style error */
{
fprintf(stderr, "%s: %s\n", msg, strerror(code));
exit(0);
}

void dns_error(char msg) / dns-style error */
{
fprintf(stderr, "%s: DNS error %d\n", msg, h_errno);
exit(0);
}

void app_error(char msg) / application error */
{
fprintf(stderr, "%s\n", msg);
exit(0);
}

Unix风格

成功时返回void,返回错误时包装函数打印一条信息,然后退出

void Kill(pid_t pid, int signum)
{
int rc;

if ((rc = kill(pid, signum)) < 0)
unix_error("Kill error");

}
Posix风格

成功时返回void,错误返回码中不会包含有用的结果

void Pthread_detach(pthread_t tid) {
int rc;

if ((rc = pthread_detach(tid)) != 0)
posix_error(rc, "Pthread_detach error");

}

DNS风格

struct hostent *Gethostbyname(const char *name)
{
struct hostent *p;

if ((p = gethostbyname(name)) == NULL)
dns_error("Gethostbyname error");
return p;

}

附录A 错误处理

Unix系统中的错误处理

1.Unix风格的错误处理

if ((pid = wait(NULL)) < 0){
fprintf(stderr, "wait error: %s\n",strerror(errno));//strerror函数返回某个errno值的文本描述
exit(0);
}

2.Posix风格的错误处理


if((retcode = pthread_create(&tid, NULL, thread, NULL) != 0) {
fprintf(stderr,"pthread_create error:%s\n",
strerror(retcode));
exit(0);
}

2.DNS风格的错误处理


if((p = gethostbyname(name)) == NULL) {
fprintf(stderr,"gethostbyname error:%s\n",
hstrerror(retcode));
exit(0);
}




资料参考来自:《深入理解计算机系统》
资料参考来自:20135202博客http://www.cnblogs.com/20135202yjx/p/4947272.html

posted @ 2015-11-15 09:19  20135330张若嘉  阅读(368)  评论(0编辑  收藏  举报