一、系统调用(API)
1、系统调用概念
系统调用是指操作系统提供给用户的一组“特殊”接口,用户程序可以通过这组“特殊”接口来获得操作系统内核提供的的服务
2、为什么用户程序不能直接访问系统内核提供的服务呢?
由于在Linux中,为了更好地保护内核空间,将程序的运行空间分为内核空间和用户空间(也就是常称的内核态和用户态),它们分别运行在不同的级别上,在逻辑上是相互隔离的。因此,用户进程在通常情况下不允许访问内核数据,也无法使用内核函数,它们只能在用户空间操作用户数据,调用用户空间的函数。
3、用户编程接口(API)
系统调用并不是直接与程序员进行交互的,它仅仅是一个通过软中断机制向内核提交请求,以获取内核服务的接口。在实际使用中程序员调用的通常是用户编程接口—API
系统命令相对API更高了一层,它实际上是一个可执行程序,它的内部引用了用户编程接口(API)来实现相应的功能
将程序的运行空间分为内核空间和用户空间(也就是常称的内核态和用户态)
4、Linux 文件
Linux一点哲学,“一切皆为文件”;在Linux中对目录和设备(包含硬件设备)的操作都等同于对文件的操作;
Linux文件可分为:普通文件(-),目录文件(d),链接文件(l),(硬件)设备文件(b/c),套接口文件(s),有名管道(p);
①普通文件类型
Linux中最多的一种文件类型, 包括 纯文本文件(ASCII);二进制文件(binary);数据格式的文件(data);各种压缩文件.第一个属性为 [-]
②目录文件
就是目录, 能用 # cd 命令进入的。第一个属性为 [d],例如 [drwxrwxrwx]
③块设备文件
块设备文件 : 就是存储数据以供系统存取的接口设备,简单而言就是硬盘。例如一号硬盘的代码是 /dev/hda1等文件。第一个属性为 [b]
④字符设备
字符设备文件:即串行端口的接口设备,例如键盘、鼠标等等。第一个属性为 [c]
⑤套接字文件
这类文件通常用在网络数据连接。可以启动一个程序来监听客户端的要求,客户端就可以通过套接字来进行数据通信。第一个属性为 [s],最常在 /var/run目录中看到这种文件类型
⑥管道文件
FIFO也是一种特殊的文件类型,它主要的目的是,解决多个程序同时存取一个文件所造成的错误。FIFO是first-in-first-out(先进先出)的缩写。第一个属性为 [p]
⑦链接文件
类似Windows下面的快捷方式。第一个属性为 [l],例如 [lrwxrwxrwx]⑧堆栈文件
如LIFO。第一个属性为[f].
查看文件命令: ls -l 或(ls ll)--—查看文件; ls -ld -—查看路径;
举例一:编写 filecpy.c 实现文件的复制。
命令 :./filecpy file1 file2
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#define BUFF_SIZE 1024
int main(int argc, char *argv[])
{
int fd_op;
int fd_opa;
int bytes_read;
int bytes_write;
char *ptr = NULL;
char buff[BUFF_SIZE];
if(3 != argc)
{
printf("please input file and aim file!\n");
exit(0);
}
if((fd_op = open(argv[1], O_RDONLY)) == -1)
{
perror("open error!");
exit(-1);
}
if((fd_opa = open(argv[2], O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
{
perror("open error!");
close(fd_op);
}
while(bytes_read = read(fd_op, buff, 1024))
{
if(bytes_read < 0)
{
perror("read error!");
break;
}
else
{
ptr = buff;
while(bytes_write = write(fd_opa, ptr, bytes_read))
{
if(bytes_write < 0)
{
perror("write error!");
break;
}
else if(bytes_write < bytes_read)
{
bytes_read -= bytes_write;
ptr += bytes_write;
}
else if(bytes_write == bytes_read)
{
break;
}
}
if(bytes_write < 0)
{
break;
}
}
}
close(fd_op);
close(fd_opa);
return 0;
}
举例二 :编写一个如下所示的文件( three_hello.txt)
三个 hello 各占一行:
hello
hello
hello
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i;
int fd;
int bytes_read;
int bytes_write;
char buff[5] = "hello";
char filename[6];
printf("please input filename:\n");
scanf("%s", filename);
if((fd = open(filename, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1)
{
perror("open erroe!");
exit(-1);
}
for(i = 0; i < 3; i++)
{
if((bytes_write = write(fd, buff, 5)) == -1)
{
perror("write error!");
break;
}
write(fd, "\n", 1);
}
lseek(fd, 0, SEEK_SET);
for(i = 0; i < 3; i++)
{
memset(buff, 0, sizeof(buff));
bytes_read = read(fd, buff, 5);
write(1, buff, 5);
memset(buff, 0, sizeof(buff));
bytes_read = read(fd, buff, 1);
write(1, buff, 1);
}
close(fd);
return 0;
}
以上代码 将buff[5] 改为 buff[6] 会更简单!
二、C库函数
举例一:编写 filecpy.c 实现文件的复制。
命令 :./filecpy file1 file2
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp1;
FILE *fp2;
char ch;
if((fp1 = fopen(argv[1], "r")) == NULL)
{
printf("not open file!\n");
exit(0);
}
if((fp2 = fopen(argv[2], "w+")) == NULL)
{
printf("not open file!\n");
fclose(fp1);
}
ch = fgetc(fp1);
while(ch != EOF)
{
fputc(ch, fp2);
ch = fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
举例二:合并文件
方法一:按字符一个一个操作!
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp1;
FILE *fp2;
FILE *fp3;
char ch1;
char ch2;
char ch;
if((fp1 = fopen("text1.txt", "r")) == NULL)
{
printf("not open file!\n");
exit(-1);
}
if((fp2 = fopen("text2.txt", "r")) == NULL)
{
printf("not open file!\n");
fclose(fp1);
}
if((fp3 = fopen("text3.txt", "w+")) == NULL)
{
printf("not open file!\n");
fclose(fp1);
fclose(fp2);
}
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
while((ch1 != EOF) && (ch2 != EOF))
{
if((ch1 > '9') || (ch1 < '0'))
{
fputc(ch1, fp3);
}
else
{
ch = (((ch1 - '0') + (ch2 - '0')) + '0');
fputc(ch, fp3);
}
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}
方法二:按照两位数相加,可以有进位。
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp1;
FILE *fp2;
FILE *fp3;
char ch1;
char ch2;
char ch;
int k;
int j;
int sum;
int count = 0;
int num1 = 0;
int num2 = 0;
if((fp1 = fopen("text1.txt", "r")) == NULL)
{
printf("not open file!\n");
exit(-1);
}
if((fp2 = fopen("text2.txt", "r")) == NULL)
{
printf("not open file!\n");
fclose(fp1);
}
if((fp3 = fopen("text3.txt", "w+")) == NULL)
{
printf("not open file!\n");
fclose(fp1);
fclose(fp2);
}
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
while((ch1 != EOF) && (ch2 != EOF))
{
if((ch1 > '9') || (ch1 < '0'))
{
fputc(ch1, fp3);
}
else
{
k = (ch1 - '0');
j = (ch2 - '0');
num1 = num1*10 + k;
num2 = num2*10 + j;
count++;
}
if(2 == count)
{
sum = num1 + num2;
ch = (sum/10 + '0');
fputc(ch, fp3);
ch = (sum%10 + '0');
fputc(ch, fp3);
num1 = 0;
num2 = 0;
count = 0;
}
ch1 = fgetc(fp1);
ch2 = fgetc(fp2);
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
return 0;
}