1 认识文件的描述符号
不允许访问内核设备和内存但可以通过内核系统函数去访问
但对每个内核对象进行编号ID:
如果访问内核对象,只能通过ID
编程模型:
申请得到一个ID
在内核系统函数中使用ID得到对应的内核对象数据
2 怎么访问文件
使用函数 传递一个文件 系统打开文件 加载文件 返回ID使用函数 传递ID 得到数据
使用函数传递ID 告诉系统释放文件
ID:文件描述符 file description (fd)
每个程序执行时都有个目录存放打开的文件描述符 /proc/${pid}/fd
其中默认开启0 1 2 三个对象
0 标准输出
1 标准输入
2 错误输出
其实它们打开的都是同一个文件(只是打开方式不同而已)
lrwx------ 1 zhao zhao 64 2013-05-30 07:21 0 -> /dev/pts/0
lrwx------ 1 zhao zhao 64 2013-05-30 07:21 1 -> /dev/pts/0
lrwx------ 1 zhao zhao 64 2013-05-30 07:21 2 -> /dev/pts/0
3 操作文件描述符
写文件#include <unistd.h>
ssize_t write(int fd,
const void *buf, //写入内核对象
size_t count);//写入数据大小
返回:
>0 实际写入的数据个数
-1 写入错误
读文件
ssize_t read(int fd,
void *buf, //返回数据的空间
size_t count);//空间大小
返回:
>0 :实际读取的文具
=0 碰到文件结束符号EOF (ctrl+d)
-1 读取错误
基于文件的描述符号
1得到文件描述符
a文件类型普通文件 -
目录文件 d
链接文件 l
管道文件 p
套接字文件 s
字符设备文件 c
块设备文件 b
find / -type c 查找字符设备文件
b文件属性
1属性的表达方式:绝对模式 字符模式
拥有者 组用户 其他用户
2文件的权限属性:
读
写
执行
粘附位 :t
设置位权限 :s
t粘附位(防止有写权限的用户删除文件)
1:表示粘附设置
t对写文件有意义
无效的粘附位使用T表示
chmod o+t xxx
s设置位(向其他用户开放拥有者权限的权限)
2:组设置位
4:组用户设置位
s对执行有效
无效的设置位使用S表示
chmod u+s xxx
比如程序员a 写了个程序可以读写文件txt, 这时用户b来使用程序,但用户b没有对文件的读写权限,这时就会出错.
假如程序员给程序设置了设置位, b在使用程序时也会获得和a一样的权限.
2通过文件描述符读写数据
open函数#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open(const char *pathname, //文件名
int flags,//open的方式(创建/打开)
mode_t mode);// 文件属性,创建的时候有效
返回值
>=0 返回内核文件描述符
=-1 打开/创建失败
open的方式
必选方式: O_RDONLY O_WRONLY O_RDWR 必选一个
创建; O_CREATE
可选方式:
对打开可选方式 : O_APPEND 追加 O_TRUNC 清空数据
对创建可选方式 : O_EXCL 与O_CREATE共用时 ,若文件存在时打开失败
组合:
创建 O_RDWR | O_CREATE 读写打开,若不存在创建
O_RDWR | O_CREATE | O_EXCL 创建文件且读写打开 若已文件存在打开失败
打开 O_RDWR 打开
O_RDWR|O_APPEND 追加打开
O_RDWR|O_TRUNC 截断打开
文件属性:
建议使用8进制数
文件创建的实际属性受到权限屏蔽(umask)的影响
umask //显示屏蔽属性
umake 0666 //设置权限屏蔽 就是说创建0777的文件 实际只有0111
关闭文件
void close(int fd);
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main()
{
int fd;
char name[20];
short age;
float score;
char sex;
//创建一个新文件 若文件存在 错误
fd = open("date.dat",O_RDWR|O_CREAT|O_EXCL,0666);
if(fd < 0)
{
perror("open");
return 1;
}
//以便读取 设置名字为5字节的字符串
memcpy(name,"tom ",sizeof("tom "));
age = 18;
score = 99.0;
sex = 'f';
write(fd,name,sizeof("tom "));
write(fd,&age,sizeof age);
write(fd,&score,sizeof score);
write(fd,&sex,sizeof sex);
memcpy(name,"jack",sizeof("jack"));
age=20;
score=98;
sex='f';
write(fd,name,sizeof("jack"));
write(fd,&age,sizeof(short));
write(fd,&score,sizeof(float));
write(fd,&sex,sizeof(char));
lseek(fd,0,SEEK_SET); //移动文件指针
read(fd,name,5);
read(fd,&age,sizeof age);
read(fd,&score,sizeof score);
read(fd,&sex,sizeof sex);
printf("name:%s age:%d score:%f sex %c\n",name,age,score,sex);
read(fd,name,5);
read(fd,&age,sizeof age);
read(fd,&score,sizeof score);
read(fd,&sex,sizeof sex);
printf("name:%s age:%d score:%f sex %c\n",name,age,score,sex);
close(fd);
}
/*
zhao@ubuntu:~/unix/3$ ./open
name:tom age:18 score:99.000000 sex f
name:jack age:20 score:98.000000 sex f
*/
3文件描述符号和重定向
isatty(int fd)
判断文件描述符是否与终端绑定
返回1 文件描述符与终端有关
返回0 不是终端
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
int main()
{
int fd;
printf("hello\n");
write(1,"world\n",6);
fd = open("/dev/tty",O_WRONLY);
if(isatty(fd))
{
write(1,"notredir\n",9);
}
else
{
write(1,"redir\n",6);
}
write(fd,"killer\n",7);
}