Linux:进程的基础I/O

  • List item

在C语言中,任何程序运行后称为进程执行时默认会打开三个输入输出流:stdin、stdout、stderr;stdin:标准输入,对应设备:键盘、stdout:标准输出,对应设备:显示器、stderr:标准错误,对应设备:显示器
注意:读写位置在起始位置,注意不要覆盖写入,文件内容有可能会有空字符(\0),从文件读取数据进行处理;

系统文件I/O

系统接口主要是这几个,分别是:read、write、open、lseek、close

  • open
    先使用man手册查看open的使用方法,例如:
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>

 int open(const char *pathname, int flags);
 int open(const char *pathname, int flags, mode_t mode)

open函数是不定参函数,实际上只有一个;
其中pathname表示要打开或者创建的目标文件名称,flags表示以什么方式打开,可以传入多个参数选项,参数有:
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:可读可写打开
这三个宏,必须指定一个且只能指定一个(必选参数)
可选参数:
O_APPEND:追加写
O_CREAT:若文件不存在,则创建它,需要使用mode选项,来指明新文件的访问权限
O_EXCL:通常与O_CREAT同时使用表示文件不存在则创建,已经存在则报错返回;
O_TRUNC;打开文件的同时,清空文件原有内容;
因此C语言中r+相当于O_RDWR,w+相当于O_RDWR|O_TRUNC|O_CREAT,a+相当于O_RDWR|O_CREAT|O_APPEND;
例如:

 #include <stdio.h>
 #include <errno.h>
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 int main()
 {
 		umask(0);
        int fd=open("log.txt",O_WRONLY|O_CREAT,0);
        if(fd<0)
        {
                printf("open error");
                return 0;
        }
        close(fd);
}

在这里我们将mode(权限)先指定为0,因为当前目录并不存在log.txt文件,因此要使用O_CREAT宏,进行按位或运算,运行结果是

[Daisy@localhost LinuxCode]$ cat log.txt
cat: log.txt: 权限不够

可以看到这时权限不够,因为这时传的mode是0,这时将mode改成

 int fd=open("log.txt",O_WRONLY|O_CREAT,0644);

这时运行得到log.txt的权限的确是644:

-rw-r--r--. 1 Daisy Daisy     0 10月 17 18:41 log.txt

这时就可以进行写操作了,例如:

 1 #include <stdio.h>
 2 #include <errno.h>
 3 #include <string.h>
 4 #include <sys/types.h>
 5 #include <sys/stat.h>
 6 #include <fcntl.h>
 7 #include <unistd.h>
 8 int main()
 9 {
10         int fd=open("log.txt",O_WRONLY|O_CREAT,0644);
11         if(fd<0)
12         {
13                 printf("open error");
14                 return 0;
15         }
16         const char* msg="hello bit\n";
17         write(fd,msg,strlen(msg));
18         close(fd);
19 
20 }

此时运行成功后可以看到log.txt的内容是:

[Daisy@localhost LinuxCode]$ cat log.txt
hello bit

发现的确写进去了。那么这个fd是什么呢,例如:

   1 #include <stdio.h>
  2 #include <errno.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/stat.h>
  6 #include <fcntl.h>
  7 #include <unistd.h>
  8 int main()
  9 {
 10         int fd0=open("log0.txt",O_WRONLY|O_CREAT,0644);
 11         int fd1=open("log1.txt",O_WRONLY|O_CREAT,0644);
 12         int fd2=open("log2.txt",O_WRONLY|O_CREAT,0644);
 13         int fd3=open("log3.txt",O_WRONLY|O_CREAT,0644);
 14         int fd4=open("log4.txt",O_WRONLY|O_CREAT,0644);
 15         int fd5=open("log5.txt",O_WRONLY|O_CREAT,0644);
 16        //if(fd<0)
 17        //  {
 18        //         printf("open error");
 19        //         return 0;
 20        //   }       
 21         printf("fd0:%d\n",fd0);
 22         printf("fd1:%d\n",fd1);
 23         
 24         printf("fd2:%d\n",fd2);
 25         printf("fd3:%d\n",fd3);
 26         printf("fd4:%d\n",fd4);
 27         printf("fd5:%d\n",fd5);
 28        // const char* msg="hello bit\n";
 29        //  write(fd,msg,strlen(msg));
 30         close(fd0);
 31         close(fd1);
 32         close(fd2);
 33         close(fd3);
 34         close(fd4);
 35         close(fd5);
 36 }

发现fd(文件描述符)是:

[Daisy@localhost LinuxCode]$ ./mywrite
fd0:3
fd1:4
fd2:5
fd3:6
fd4:7
fd5:8
[Daisy@localhost LinuxCode]$ ./mywrite
fd0:3
fd1:4
fd2:5
fd3:6
fd4:7
fd5:8

发因此可以得出结论:一个进程默认打开三个文件描述符,分别叫做0 1 2,0对应标准输入,1对应标准输出,2对应标准错误,比如:

  8 int main()
  9 {
 10 
 11         const char* msg="hello bit\n";
 12         write(1,msg,strlen(msg));
 13 } 

这时就是写入到了标准输出,结果是:

[Daisy@localhost LinuxCode]$ ./mywrite
hello bit
  • write
    它的函数原型是:
ssize_t write(int fd, const void *buf, size_t count);

其中参数fd表示文件描述符,buf表示从buf中写入到fd中,count表示写了多少字节的数据,它的返回值表示成功返回所写的字节数,若为0表示没有写入数据;

  • read
    它的函数原型是:
ssize_t read(int fd, void *buf, size_t count);

其中参数表示文件描述符,buf表示从fd中读取的数据放在buf中,count表示读取了多少字节,返回值成功返回读取到的字节数,为0表示文件描述符,此返回值受文件剩余字节数限制.当返回值小于指定的字节数时并不意味着错误;这可能是因为当前可读取的字节数小于指定的字节数(比如已经接近文件结尾,或者正在从管道或者终端读取数据,或者 read()被信号中断). 发生错误时返回-1,并置 errno 为相应值.在这种情况下无法得知文件偏移位置是否有变化;
例如:

  1 #include <stdio.h>
  2 #include <errno.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/stat.h>
  6 #include <fcntl.h>
  7 #include <unistd.h>
  8 int main()
  9 {       
 10         int fd=open("log0.txt",O_RDONLY);
 11         if(fd<0)
 12         {       
 13                 printf("open error\n");
 14         }       
 15         char c;
 16         while(read(fd,&c,1)>0)
 17         {       
 18                 putchar(c);
 19         }       
 20         close(fd);
 21         return 0;
 22 }

这时就可以读出log0.txt中的内容,结果是:

[Daisy@localhost LinuxCode]$ ./mywrite
hello world!
hello world!
hello world!

的确读出了log0.txt中的内容,read的返回值为0时退出循环。
再例如:


  1 #include <stdio.h>
  2 #include <errno.h>
  3 #include <string.h>
  4 #include <sys/types.h>
  5 #include <sys/stat.h>
  6 #include <fcntl.h>
  7 #include <unistd.h>
  8 int main()
  9 {
 10         int fd=open("log0.txt",O_RDONLY);
 11         if(fd<0)
 12         {
 13                 printf("open error\n");
 14         }
 15         char c[1024];
 16         ssize_t s=read(fd,c,1024);
 17         if(s>0)
 18         {       
 19                 c[s]=0;//因为read不是C中的函数,不能保证将\0读到c中
 20                 printf("s:%d\n",s);
 21                 printf("%s\n",c);
 22         }
 23         close(fd);
 24         return 0;
 25 }

此时的运行结果是:

[Daisy@localhost LinuxCode]$ ./mywrite
s:39
hello world!
hello world!
hello world!

发现也的确读出了log0.txt中的内容。

  • lseek
    它的函数原型是:
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);

其中参数fd是文件描述符,offset表示偏移量,whence与C语言中的fseek一样;

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

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

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

    抵扣说明:

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

    余额充值