coding第11天1.3

本文探讨了Unix系统调用中的read和write函数,以及如何用它们实现getchar函数。同时,解析了open与creat的区别,展示了在cp命令中的使用实例,包括文件描述符、静态缓冲区和权限设置。
摘要由CSDN通过智能技术生成

unix系统接口

两个系统调用
int n_read=read(int fd,char *buf,int n);
int n_written=write(int fd,char *buf,int n);

对于系统调用read和write,第一个参数为文件描述符,第二个参数为程序中存放读或者写的字符数组,第三个参数为要传输的字节数。
用read构造getchar函数,因为没有重定向所以系统默认从标准输入中读即文件描述符0—stdin
下面这个版本 依次读一个字符并且返回一个字符。

#include <unistd>

int getchar(void)
{
	char c;
	return (read(0,&c,1)==1)?(unsigned char)c:EOF;
}

下面这个版本,依次读入一个数组并返回一个字符

#include <unistd>

int getchar(void)
{
	static char buf[BUFSIZE];
	static char *bufp=buf;
	static int n=0;

	if(n==0)
	{
		n=read(0,buf,sizeof(buf));
		bufp=buf;
	}
	return (--n>=0)?(unsigned char)*bufp++:EOF;
}

问题:
调用函数第一次的时候,n初始化为0,执行n0时候的语句,从标准输入中读取字符串,并将bufp指向该字符数组。然后–n,并返回bufp指向的字符,并将bufp指向下一个字符。
但是第二次调用的时候,不担心n与bufp重新初始化,n=0,bufp指向第一个字符。等于重新输入没有缓冲区么。相当于只输出第一个字符,其他字符全被吞掉。
答:
不会,上述函数中的buf[BUFSIZE]声明为静态变量,此时静态变量只进行一次初始化操作,并且与局部变量不同的是,不会应为函数调用的结束,静态变量就消失,而实仍旧存在。
静态变量的生存周期与外部变量是一致的,不同点在于,静态变脸保护了数据,也可以比喻成静态变量就是将数据指明给某些特定函数使用的外部变量。
所以对于buf[BUFSIZE],bufp以及n这几个静态变量
1,只初始化一次;
2,–n>=0指明缓冲区还有字符
3,*bufp++将获得bufp指向的字符,并将bufp加一,
4,if当中的bufp=buf也是必须的,因为初始化只在第一次执行,在后面当n
0时候,需要将bufp重新指向数组首位。

系统调用open与creat

open

#include <fcntl.h>

int fd;
int open(char *name,int flags,int perms);
fd=open(name,flags,perms);

open中
第一个参数为文件名称。
第二个参数为文件打开方式,在<fcntl.h>中定义,有
O_RDONLY
O_WDONLY
O_EDWR
意义如名称,只读,只写,读写
第三个参数为访问权限。
返回值为文件描述符

open打开一个不存在的文件将发生错误,可以用creat创建或覆盖已有的旧文件。

creat

int creat(char *name,int perms);
fd=creat(name,perms);

creat
第一个参数为文件名
第二个参数为访问权限。访问权限用三位的8进制数描述

返回值为,正常返回一个文件描述符,错误返回-1.

下面为一个简化版本的unix程序cp

#include <stdio.h>
#include <fcntl.h>
#include <unistd>

#define PERMS 0666
int main(int rgc,char *argv[])
{
	int f1,f2,n;
	char buf[BUFSIZE];

	if(argc!=3)
	{
		fprintf(stderr,"Usage:cp from to");
	}
	if((f1=open(argv[1],O_RDONLY,0))==-1)
	{
		fprintf(stderr,"cp:cant open %s",argv[1]);
	}
	if((f2=creat(argv[2],PERMS))==-1)
	{
		fprintf(stderr,"cp:cant creat %s.mode %03o",argv[2],PERMS);
	}
	while((n=read(f1,buf,BUFSIZE))>0)
	{
		if(write(f2,buf,n)!=n)
		{
			fprintf(stderr,"cp:write error on file %s",argv[2]);
		}
	}
	return 0;
}

上述的函数,仅仅复制一个文件,不允许目录作为第二个参数 ,并且目标文件的权限不是通过复制得到的,而实通过重新定义。
可以发现每次调用read和write进行读写的位置紧跟在前一次操作的位置之后。
有一种在文件中移动到任意位置的函数;

long Iseek(int fd,long offset,int origin);

fd为文件描述符,offset相对于origin的偏移量,origin值为0、 1、2.
语法意义为从文件开始、当前位置以及文件 结束开始算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来根华子冷静下

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值