系统级I/O的一些代码实验

首先记录一下关于csapp.c文件的链接问题:
(以下为转载内容,原文请参见:关于csapp.h和csapp.c 的链接问题
方法一:

  • 在同一目录之下分别把csapp.c和其他需要运行的c语言源程序编译成可重定位目标文件格式,拓展名为“.o”;
  • 由于csapp.c中有关于线程的内容,所以将两者链接时记得带上-lpthread选项:gcc -o   * csapp.o  *.o -lpthread

方法二:

  • 在csapp.h里面最后#end if之前添加   #include <csapp.h>   
  • 在要编译的头文件添加#include <csapp.h>
  • 将csapp.c与csapp.h复制添加到/usr/incude目录下:
    cp SOURCE(S)    /usr/include
    SOURCE(S)的意思就是你要复制的源文件
  • 编译时同样记得加上-lpthread选项

以下正式开始

statcheck.c(文件基本信息)

/* $begin statcheck */
#include "csapp.h"

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

    /* $end statcheck */
    if (argc != 2) {
	fprintf(stderr, "usage: %s <filename>\n", argv[0]);
	exit(0);
    }
    /* $begin statcheck */
    Stat(argv[1], &stat);
    if (S_ISREG(stat.st_mode))     /* Determine file type */
	type = "regular";
    else if (S_ISDIR(stat.st_mode))
	type = "directory";
    else 
	type = "other";
    if ((stat.st_mode & S_IRUSR)) /* Check read access */
	readok = "yes";
    else
	readok = "no";
    printf("type: %s, read: %s\n", type, readok);
    exit(0);
}

运行结果:

情形一:不带参数运行

输出了当前(可执行文件)位置信息
可见argv[0]中存储的就是当前位置,是默认传入的
而int型argc指的就是传入main函数的参数个数

情形二:带文件名参数

在这里插入图片描述

struct stat:结构体类型,用于存储文件的一些基本信息
st_mode:文件的模式位,设置模式位实际上就是
S_ISREG(stat.st_mode):传入文件的mode参数,检查bit位,对应文件是否是一个普通文件
S_ISDIR(stat.st_mode):是否是一个目录
S_IRUSR:宏定义,拥有者可读,若st_mode设置了相应的模式位,则与之按位与的结果就为真

files1.c(I/O重定向)

#include "csapp.h"

int main(int argc, char *argv[])
{
    int fd1, fd2, fd3;
    char c1, c2, c3;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    fd2 = Open(fname, O_RDONLY, 0);
    fd3 = Open(fname, O_RDONLY, 0);
    dup2(fd2, fd3);

    Read(fd1, &c1, 1);
    Read(fd2, &c2, 1);
    Read(fd3, &c3, 1);
    printf("c1 = %c, c2 = %c, c3 = %c\n", c1, c2, c3);

    Close(fd1);
    Close(fd2);
    Close(fd3);
    return 0;
}

运行结果:
在这里插入图片描述
Open()是对open()的封装
int open(char *filename,int flags,mode_t mode):参数列表依次是文件名,访问权限,模式位。
访问权限指示怎样访问这个文件,可以是O_RDONLY,O_WRONLY,O_RDWR,O_CREAT,O_TRUNC,O_APPEND即它们的或;
模式位指定了新文件的访问权限

int dup2(int oldfd,int newfd):重定向,将文件描述符表项oldfd复制到newfd,如果在此之前newfd已经存有值了,会先关闭newfd指向的文件表

关于文件表:
如下图,每次open都创建一个文件表,v-node是共享的,即视一个文件被打开多次都只有一个v-node表
在这里插入图片描述

关于fflies.c中的过程如下:
在这里插入图片描述
下面一段代码,有助于理解一下文件描述符,文件表以及文件共享

files1.c

#include "csapp.h"

int main(int argc, char *argv[])
{
    int fd1;
    int s = getpid() & 0x1;
    char c1, c2;
    char *fname = argv[1];
    fd1 = Open(fname, O_RDONLY, 0);
    Read(fd1, &c1, 1);
    if (fork()) {
	/* Parent */
	sleep(s);
	Read(fd1, &c2, 1);
	printf("Parent: c1 = %c, c2 = %c\n", c1, c2);
    } else {
	/* Child */
	sleep(1-s);
	Read(fd1, &c2, 1);
	printf("Child: c1 = %c, c2 = %c\n", c1, c2);
    }
    return 0;
}

abcde.txt

abcde

运行结果如下:

此结果不唯一
Read()同样是对read()的封装
s = getpid() & 0x1——使得子进程和父进程一个休眠1秒一个休眠0秒(sleep(s)和sleep(1-s))
文件表示意图如下:
在这里插入图片描述
因为子进程得到父进程的fork()时所有信息的一个复制,故文件描述符表理所当然也被复制过来,所以它们共享相同的文件表(文件表是所有进程共享的),文件表中保存了在文件中读/写文件的当前位置。因此运行结果之一就是如上。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值