The c programing languag chap8

第八章unix系统接口的学习哦

主要就是讲了使用unix系统接口封装我们经常使用的操作
getchar putchar getc putc malloc free 操作,让我们
揭开c语言封装的面纱,一窥其真面目。

1. 文件描述

unix系统不同于window系统的地方就是,unix的理念就是一切皆文件,
unix的一切都是对文件的处理,你从键盘输入的符号就是一个文件在处理,我们
只要读取这个文件就可以得到,你输入的符号。问题了,我们怎么知道去读取哪个
文件,unix就设计了文件描述这个概念用来表示文件,我们只要得到一个文件的文件
描述就可以去操作这个文件,就像我们之前用文件的指针来处理文件一样,但是这里的
文件描述是一个数字,比如我们之前用的sdtin stdout stderr 就是三个文件,文件描述
分别是0 1 2,这个是c语言定义的。

2. 底层I/O调用:read write

/* fd is a file desriptor,buf is an array for store the file content,n is the
number of bytes to be transferred ,
return : n_read is the number of bytes transferred , 0 bytes implies end the file
and -1 indicates an error of some sort.
*/
int n_read = read(int fd, char *buf, int n);

int n_write = write(int fd, char *buf, int n);
example: 
void test()
{    
    char buf[100];
    int n;
    while (n = (read(0, buf, 100) > 0 ) {
        wirte(1, buf, n);
        //gets puts 也可以
    return 0;    
    }

}

4. 随机访问 lseek

/*
    arguments : fd is file descriptor, 
    offset is taken relative to the location specified by origin
    origin can be 0,1,2 to specify the file begining,current,end position
    return : a long that gives the new position in the file or -1 if an error occurs
*/
long lseek(int fd, long offset, int origin);

5. 例子–fopen和getc

5.1 expamle.c

#include "file.c"
/*this struct is for exercise 8-2 */
struct flag_field {
    unsigned is_read : 1;
    unsigned is_write : 1;
    unsigned is_unbuf: 1;
    unsigned is_buf: 1;
    unsigned is_eof : 1;
    unsigned is_err : 1;
}
main()
{
  int c =0;
  char s[100];
  FILE *fp = NULL;
if ((fp = fopen("./chap1.c","w"))==NULL)
  {
    char *a = "exist\n";
    write(1,a,7);
   }
  while ((c =getc(stdin))!=EOF)
   {
    putchar(c) ;
    }
    fflush(stdout);
    fclose(stdout);
    //cout(stdout->base);
  if (c == EOF)
  cout("the file is end ======================================\n");
}

5.2 file.c 定义的fopen fclose 等文件操作

#include <fcntl.h>
#include "syscalls.h"  //for the system call notice that this is not a standard fil
#include <stdlib.h>
#include "utility.c" //自己编写的一些strlen strcat 方法,为了使用方便
#ifndef NULL
#define NULL 0
#endif
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20 //max files open at once
#define cout(x) write(1,(x),(_strlen(x))) //写这个是为了调试方便
typedef struct _iobuf {
    int cnt; // the numner of left characters 
    char *ptr; // next character postion
    char *base; // location of buffer
    int flag; // mode of file access
    int fd; //file descriptor
} FILE;

enum _flags {
    _READ   = 01,   // file open for reading 
    _WRITE  = 02,   // file open for writing 
    _UNBUF  = 04,   // file is unbuffered 
    _EOF    = 010,  // EOF has occured on thi file 
    _ERR    = 020   // error occured on this file
};



 //define file array and initialized for stdin,stdout,stderr
 FILE _iob[OPEN_MAX] = {
     {0, (char *)0, (char *)0, _READ, 0},
    {0, (char *)0, (char *)0, _WRITE, 1},
     {0, (char *)0, (char *)0, _ERR| _UNBUF, 2}
 };

//int _fillbuf(FILE *fp);
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])

int _fillbuf(FILE *);       // read characters form file to fillfull the file buffer
int _flushbuf(int, FILE *);  // write all characers of buffer to this file

#define feof(P)     (((P)->flag & _EOF) != 0)
#define ferror(P)   (((P)->flag & _ERR) != 0)
#define fileno(P)   ((P)->fd)

#define getc(p)     (--(p)->cnt >= 0 ? (unsigned char)*(p)->ptr++ : _fillbuf(p)) 
#define putc(x, p)  (--(p)->cnt >= 0 ? *(p)->ptr++ = (x): _flushbuf(x,p)) 

#define getchar()   getc(stdin)
#define putchar(x)   putc((x), stdout)

#define PERMS 0666 //RW  for owner, group, others
/*  open the file 
    name is file name 
    mode can be r w read
    return : FILE * 
*/
FILE *fopen(char *name, char *mode)
{   
   int fd;
   FILE *fp;

   if (*mode != 'r' && *mode != 'w' && *mode != 'a')
       return NULL;

   for (fp = _iob; fp < _iob + OPEN_MAX; fp++) 
       if ((fp->flag & (_READ | _WRITE)) == 0) 
           break; //look for  a free location 

   if (fp >= _iob + OPEN_MAX){
       return NULL;
   }    

   if (*mode == 'w') {
       fd = creat(name, PERMS);  
       cout("file mode  is  write  :\n");
   } else if (*mode == 'a') {
      if (fd = open(name, O_WRONLY , 0) == -1)
           fd = creat(name, PERMS); 
      cout("file mode  is  append  :\n");
      lseek(fd, 0L, 2);    
   } else { 
       cout("file is readonly   :\n");
       fd = open(name, O_RDONLY, 0); 
       cout(_itoa(fd));
       cout("   fd \n");
   }
   if (fd == -1)
       return NULL; 

  fp->fd = fd;
  fp->cnt = 0;
  fp->base = NULL;
  fp->flag = (*mode == 'r') ? _READ : _WRITE;
  return fp;     
} 
/* read content of the  file and write it to the buffer*/
int _fillbuf(FILE *fp)
{
    int bufsize;

    cout("_fillbuf --- -start-\n");    

    //if ((fp->flag&(_ERR|_EOF|_READ)) != _READ) //return eof if mode is not read
    if (fp->flag != _READ) //return eof if mode is not read
    {
      cout("not read to file \n");
        return EOF;
    }

    //cout("_fillbuf ---file is read-\n");    
    bufsize = (fp->flag&_UNBUF) ? 1 : BUFSIZ;  //either buf

    if (fp->base == NULL)  
        if (!(fp->base = (char *)malloc(bufsize)))
            return EOF;
    //cout("_fillbuf-----fp->base after\n ");
    fp->ptr = fp->base;
    fp->cnt = read(fp->fd, fp->ptr, bufsize);
    if (--fp->cnt < 0) {
       if (fp->cnt == -1) //end of this file

            fp->flag = _EOF;
        else 
            fp->flag = _ERR; //any error occurs
    }

    return (unsigned char) *fp->ptr++;
}

//initialized for stdin,stdout,stderr
/*FILE _iob[OPEN_MAX] = {
    {0, (char *)0, (char *)0, _READ, 0},
    {0, (char *)0, (char *)0, _WRITE, 1},
    {0, (char *)0, (char *)0, _ERR| _UNBUF, 2}
};
*/
/*
write content of buffer to the file
*/
int  _flushbuf(int x, FILE *fp)
{
    int bufsize;
    unsigned nc;
    cout("_flushbuf --- -start-\n");    

    // error : invalid pointer 
    if (fp < _iob || fp >= _iob + OPEN_MAX)
        return EOF;
    //if ((fp->flag&(_ERR|_EOF|_READ)) != _READ) //return eof if mode is not read
    if (fp->flag != _WRITE) //return eof if mode is not read
    {
        cout("not write to file \n");
        return EOF;
    }

    //cout("_flushbuf ---file is write-\n");    
    bufsize = (fp->flag&_UNBUF) ? 1 : BUFSIZ;  //either buf

    if (fp->base == NULL) { 
        if (!(fp->base = (char *)malloc(bufsize)))
            return EOF;
    } else {//write buf to this file
         nc = fp->ptr - fp->base;
         if (write(fp->fd, fp->base, nc) != nc) 
            return EOF;
    }            
    //cout("_flushbuf-----fp->base after\n ");
    fp->ptr = fp->base;
    fp->cnt = bufsize - 1;
    *fp->ptr++ = x;
    //cout("flush  : ");
    //cout(fp->base);
    //cout("================================\n");
    return x;
}
/*
fflush: flush buffer associated with fp
*/
int fflush(FILE *fp)
{
    // error : invalid pointer 
    if (fp < _iob || fp >= _iob + OPEN_MAX)
        return EOF;
    if (fp->flag & _WRITE)
        _flushbuf('\0',fp);
    //把写进去的\0重新取出来    
    fp->ptr = fp->base;
    fp->cnt = (fp->flag&_UNBUF) ? 1 : BUFSIZ;
    return 0;
}
/*close file */
int fclose(FILE *fp)
{
    int rc;
    if ((rc = fflush(fp))!=EOF)
    {
        free(fp->base);
        fp->ptr = NULL;
        fp->cnt =0;
        fp->flag &= ~(_READ | _WRITE); 

    }
    return rc;
}
/*
fseek : seek with a file pointer
*/
int fseek(FILE *fp, long offset, int origin)
{
    unsigned nc; // the number of  flush
    long rc = 0;
    if (fp->flag & _READ) {
        if (origin == 1) //current position
            offset -= fp->cnt;//need think about flush
        rc = lseek(fp->fd, offset, origin);         
        fp->ctn = 0;
    } else if (fp->flag & _WRITE) {
        //write buffer to this file
        if ((nc = fp->ptr - fp->base) > 0)
            if (write(fp->fd, fp->base, nc) != nc)
               rc = -1;
        if (!rc)       
            rc = lseek(fp-fd,offset, origin);
    }

    return (rc == -1) ? -1 : 0;
}

5.3 utility.c 定义的一些string的操作(自己实现的), _strlen _strcat 等

#define abs(x) ((x)<0?-(x):(x)) 
/* 注意这里只是abs() 进行替换,如果看不懂可以看看这个
   http://blog.csdn.net/li740207611/article/details/51074103  */
/*
3-3 : expand(s1,s2)
*/
int is_digit_letter(int c)
{
    if(c >= 'a' && c <= 'z')
       return 1;
    else if(c >= '0' && c <= '9')
       return 1;
    return 0;   
}
int _strlen(char *s)
{   
    int i = 0;
    while (*s++ != '\0') 
        i++;

    return i;
}
void _reverse(char *s)
{
    int r = _strlen(s) - 1;
    int l = 0;
    int temp;
    while (l < r) {
        temp = *(s+l);
        *(s + l++) = *(s + r);
        *(s + r--) = temp;
    }
}
/* 3-4
 首先,我们知道,有符号char 的取值范围: -128127
 同样的有符号的 int 取值范围是: 2^(sizeof(int)*8-1) 到 2^(sizeof(int)*8-1)-1 
 这个时候 : 2^(sizeof(int)*8-1) 这个值,在计算机输出的时候是一个负值,这个是最大负值
 其实在补码表示的时候,他的补码和反码一样,举个例子char -128 补码 反码都是 1000 0000
 所以,假如我们要把最大负数,转成字符串输出,就不能直接对n进行 n=-n 赋值操作,这样的操作
 计算的结果肯定有问题,我们把n=-n 赋值操作,间接的放到处理数据的过程中去,这样就不存在
 最大值的问题,因为处理数据的过程中,结果范围是 0-9
 itoa : convert n to characters in s
 and can handle the largest negative numbner
 n = -2^(wordsize-1),regardless of the machine on which it runs*/
char *_itoa(int n) 
{
  int sign, i;
  char *s = malloc(100);
  i = 0;
  sign = n;
  do
  {
     s[i++] = abs(n%10) + '0';
  }while(n /= 10); 
  (sign<0)? (s[i++] = '-'):' ';
  s[i] = '\0';
  _reverse(s); 
  return s;
}
void _strcat(char *s, char *t)
{

    int i = _strlen(s); 
    while ( *t != '\0')    
        *(s + i++) = *t++; 
    *(s+i) = '\0';
}

6. 例子–文件列表

第五个例子花费事件太长了,完全没有时间做下面的,这本书花费的时间太长了,得赶紧看汇编了
有空再来写吧,反正都是书上的例子。

7. 例子–内存分配器

finally,课后练习题

只做了跟file相关的那个练习题(8-2->8-4),就是 fopen fread fwrite getc putc getchar putchar
_fillbuf _flushbuf _fflush _fclose fseek, 另外那个8-2,只定义了一个结构体用来代替原来的位操作
因为大体上不变,只是把原来对位的操作,修改成结构体的操作,应该是更简单了。其余的题有空继续做。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值