您的位置:首页 > 运维架构 > Linux

Linux 文件系统编程之系统调用和标准I/O库

2017-08-09 19:37 441 查看
系统调用

访问设备驱动程序的底层函数主要有:
open:打开文件或者设备。
read:从打开的文件或者设备里面读取数据。
write:向文件或者设备写数据。
close:关闭文件或者设备。


open系统调用:
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int open (const char *path, int flags);
int open (const char *path, int flags, mode_t mode);
path表示文件名,flags用来定义准备对打开的文件进行操作的动作。
如果open调用成功,则返回一个新的文件描述符(非负整型);如果失败,就返回-1。

close系统调用:
#include <unistd.h>
int close(int filedes);
成功返回0;出错返回-1;

read系统调用:
#include <unistd.h>
ssize_t read(int filedes, const void *buf, size_t nbytes);< publishblog.blogchina.com http:>
将n个字节从文件描述符对应的文件读出放入到buf中。成功则返回实际的读取字节数。

write系统调用:
#include <unistd.h>
ssize_t write(int filedes, const void *buf, size_t nbytes);
返回值是实际写入的字节数(可能会小于nbytes);如果返回值是0,表示没有写入任何数据;如果返回值是-1,表示在write调用中出错了。
将n个字节从buf中写入到文件描述符对应的文件中。


常用标准I/O库文件函数:fopen,fwrite,fread,fclose,fflush,fseek,fgets,getchar,fputs等系列的函数

他们与系统调用的一个主要的区别在于,这是带缓冲的函数,操作的对象不是int型的文件描述符,而是fopen返回的FILE型的文件指针(*fp).对应的标准输入,输出,出错为stdin,stdout,stderr文件指针。

我把这些函数的用法全都写在这里:

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>

#define SIZE  1024

// fopen
int main0()
{
FILE* fp = fopen ("abc", "ab+");
if (NULL == fp)
{
perror ("fopen");
return -1;
}

printf ("打开文件成功\n");
return 0;
}

// fread
int main1()
{
FILE* fp = fopen ("BTree.c", "ab+");
if (NULL == fp)
{
perror ("fopen");
return -1;
}

char buf[SIZE] = {0};

// feof 判断是否读到文件结尾,如果读到文件结尾,它返回一个非0 的值
int ret;
while (ret = fread (buf, sizeof(char), SIZE-1, fp))
{
buf[ret*sizeof(char)] = '\0';
printf ("%s\n", buf);
}

if (0 == ret && !feof(fp))
{
perror ("fread");
return -1;
}

printf ("文件读取结束\n");
return 0;
}

// fwrite
int main2()
{
FILE* fp = fopen ("1.ppt", "ab+");
if (NULL == fp)
{
perror ("fopen");
return -1;
}

FILE* fp1 = fopen ("2.ppt", "ab+");
if (NULL == fp1)
{
perror ("fopen");
return -1;
}

char buf[SIZE] = {0};

// feof判断是否读到文件结尾,如果读到文件结尾,它返回一个非0 的值
int ret;
while (ret = fread (buf, sizeof(char), SIZE, fp))
{
fwrite (buf, sizeof(char), ret, fp1);
}

if (0 == ret && !feof(fp))
{
perror ("fread");
return -1;
}

printf ("文件读取结束\n");

fclose (fp);
fclose (fp1);
return 0;
}

// fgetc
int main3()
{
FILE* fp = fopen ("1.ppt", "ab+");
if (NULL == fp)
{
perror ("fopen");
return -1;
}

FILE* fp1 = fopen ("2.ppt", "ab+");
if (NULL == fp1)
{
perror ("fopen");
return -1;
}

char buf[SIZE] = {0};

// feof 判断是否读到文件结尾,如果读到文件结尾,它返回一个非0 的值
int ret;
while(1)
{
int  c = fgetc (fp);
if (EOF == c)
{
break;
}
fputc (c, fp1);
}

fclose (fp);
fclose (fp1);
return 0;
}

// 数据获取
/***************************************************************/
typedef struct student
{
int id;
char name[20];
}STU;

void write_data(STU* a, int len)
{
FILE* fp = fopen ("student", "ab+");
if (NULL == fp)
{
perror ("fopen");
return;
}

// 要写入个数
fwrite (&len, sizeof(int), 1, fp);

int i;
for (i = 0; i < len; i++)
{
// 写入数据长度
len = sizeof(a[i]);
fwrite (&len, sizeof(int), 1, fp);

// 写入数据
fwrite (&a[i], sizeof(STU), 1, fp);
}

fclose (fp);
}

// 读取数据
void read_data()
{
FILE* fp = fopen ("student", "ab+");
if (NULL == fp)
{
perror ("fopen");
return;
}

// 读记录的个数
int count;
fread (&count, sizeof(int), 1, fp);

printf ("记录个数是:%d\n", count);
int i;
STU tmp;
for (i = 0; i < count; i++)
{
int len;
fread (&len, sizeof(int), 1, fp);

// 读取数据
fread (&tmp, len, 1, fp);
printf ("id = %d, name = %s\n", tmp.id, tmp.name);
}

fclose (fp);
}

int main4()
{
int i;
STU a[20];

for (i = 0; i < 20; i++)
{
a[i].id = i;
sprintf (a[i].name, "zhang%d", i);
}

int len = sizeof(a)/sizeof(a[0]);

// 写数据
write_data(a, len);

// 读数据
read_data();

return 0;
}
/***************************************************************/

// open
int main5()
{
close(1);

// 打开一个文件
int fd = open ("test.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR |   S_IXUSR);
// int fd = open("test.txt", O_RDONLY);

if (-1 == fd)
{
printf ("打开文件失败\n");
perror ("open");
printf ("%s\n", strerror(errno));
}

printf ("fd = %d\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
printf ("asdadsafsfkj\n", fd);
// fflush(stdout);

close(fd);

return 0;

}

// read
/***************************************************************/
int main6()
{
int fd = open ("BTree.c", O_RDONLY, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}

// 缓冲区
char buf[SIZE] = {0};
ssize_t ret = read (fd, buf, SIZE-1);
if (-1 == ret)
{
perror ("read");
}

// 返回值为0 代表读到文件结尾
if (0 == ret)
{
printf ("文件读取结束\n");
}

printf ("len = %d\n", strlen(buf));
printf ("读到%d字节:%s\n", ret, buf);

return 0;
}

// 缓冲区覆盖问题
int main7()
{
int fd = open ("BTree.c", O_RDONLY, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}

char buf[SIZE] = {0};

while(1)
{
ssize_t ret = read (fd, buf, SIZE-1);
if (-1 == ret)
{
perror ("read");
}

// 返回值为0 代表读到文件结尾
if (0 == ret)
{
printf ("文件读取结束\n");
break;
}

// printf ("len = %d\n", strlen(buf));
// printf ("读到%d 字节: %s\n", ret, buf);
printf ("%s", buf);
}

return 0;
}

// 读取数据之前清空缓冲区
int main8()
{
int fd = open ("BTree.c", O_RDONLY, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}

char buf[SIZE] = {0};

while(1)
{
memset (buf, 0, SIZE);          // 清空缓冲区
ssize_t ret = read (fd, buf, SIZE-1);
if (-1 == ret)
{
perror ("read");
}

if (0 == ret)
{
printf ("文件读取结束\n");
break;
}
printf ("%s", buf);
}

return 0;
}

// 每次读完数据之后讲下一个字节置为'\0';
int main9()
{
int fd = open ("BTree.c", O_RDONLY, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}

char buf[SIZE] = {0};

while(1)
{
ssize_t ret = read (fd, buf, SIZE-1);
if (-1 == ret)
{
perror ("read");
}

if (0 == ret)
{
printf ("文件读取结束\n");
break;
}

buf[ret] = '\0';
printf ("%s", buf);
}

return 0;
}

// 读一个完整的大数据
int main10()
{
int fd = open ("BTree.c", O_RDONLY, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}

char buf[SIZE] = {0};
char* p = buf;
int count = SIZE - 1;               // 每次要读的数据个数
ssize_t ret =0;
while (ret = read (fd, p, count))
{
// 出错
if (-1 == ret)
{
if (errno == EAGAIN || errno == EINTR)
{
continue;
}
break;
}
printf ("sfjsfsjfs\n");
// 读完
if (ret == count)
{
break;
}
count -= ret;                   // 下一次要读的数据
p += ret;
}

printf ("len = %d\n", strlen(buf));
// printf ("%s\n", buf);

return 0;
}
/***************************************************************/

// write
int main11()
{
int fd = open ("abc", O_WRONLY|O_CREAT, 0777);
if (-1 == fd)
{
perror ("open");
return -1;
}
char buf[SIZE] = {0};

while(1)
{
fgets (buf, SIZE, stdin);
if (0 == strncmp ("end", buf, 3))
{
break;
}

ssize_t ret = write (fd, buf, strlen(buf));
if (-1 == ret)
{
perror ("write");
}

printf ("要写的字节数:%d,实际写的字节数:%d\n", SIZE, ret);
}

close(fd);
return 0;
}

// 文件复制
int main12()
{
// 打开要读的文件
int fd1 = open ("1.ppt", O_RDONLY);
if (-1 == fd1)
{
perror ("open fd1");
return -1;
}

int fd2 = open ("2.ppt", O_WRONLY|O_CREAT, 0777);
if (-1 == fd2)
{
perror ("open fd2");
return -1;
}

int ret = 0;
char buf[SIZE] = {0};
while (ret = read (fd1, buf, SIZE))
{
if (-1 == ret)
{
perror("read");
break;
}

write (fd2, buf, ret);
}
printf ("文件复制完成\n");
close (fd1);
close (fd2);

return 0;
}

// lseek
int main13()
{
// 打开要读的文件
int fd = open ("abc2", O_RDWR|O_CREAT, 0777);
if (-1 == fd)
{
perror ("open fd1");
return -1;
}

// 设置这个文件的偏移指针
lseek (fd, 20, SEEK_SET);

char* buf = "hello";

write (fd, buf, strlen(buf));
close (fd);

return 0;
}

// 创建一个大文件
int main14()
{
// 打开要读的文件
int fd = open ("big", O_RDWR|O_CREAT, 0777);
if (-1 == fd)
{
perror ("open fd1");
return -1;
}

// 设置这个文件的偏移指针到1G处
lseek (fd, 1024*1024*1024, SEEK_SET);

char* buf = "hello";
write (fd, "a", 1);
close (fd);

return 0;
}

// printf缓冲
int main15()
{
while(1)
{
printf ("a");
usleep (2000);
}

return 0;
}

// 文件偏移指针测试1
int main16()
{
// 打开要读的文件
int fd = open ("big", O_RDWR|O_CREAT, 0777);
if (-1 == fd)
{
perror("open fd1");
return -1;
}

printf ("%d\n", fd);
// 设置这个文件的偏移指针到1G处
lseek (fd, 20, SEEK_SET);

printf ("等待2些数据\n");
getchar();

char* buf = "hello";

write (fd, "a", 1);
getchar();

close (fd);
return 0;
}

// 文件偏移指针测试2
int main17()
{
// 打开要读的文件
int fd1 = open ("abc", O_RDWR|O_CREAT, 0777);
if (-1 == fd1)
{
perror ("open fd1");
return -1;
}

printf ("abc fd = %d\n", fd1);

int fd = open ("big", O_RDWR|O_CREAT, 0777);
if (-1 == fd)
{
perror ("open fd");
return -1;
}

printf ("bif fd = %d\n", fd);
// 设置这个文件的偏移指针到 1G处
lseek (fd, 10, SEEK_SET);

char *buf = "12345";

write (fd, buf, strlen(buf));
getchar();
close (fd);

return 0;
}

/***************************************************************/
// 随机分组
// 函数功能:互换
void swap (int* a, int i, int j)
{
int tmp = a[i];
a[i]    = a[j];
a[j]    = tmp;
}
// 函数功能:打印
void printA (int* a, int len)
{
int i;

for (i = 0; i < len; i++)
{
if (0 == i % 4)
{
printf ("\n");
}
printf ("%4d", a[len-i-1]);
}

putchar ('\n');
}

int main18()
{
srand ((unsigned int)time(NULL));

int a[40];
int i;
int len = 40;
for (i = 0; i < 40; i++)
{
a[i] = i;
}

for (i = len-1; i > 0; i--)
{
int index = rand() % (i+1);    // 获取随机数
swap (a, index, i);            // 将获得的数和最后一个互换
}

printA (a, len);

return 0;
}
/***************************************************************/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息