语言是如何实现跨平台的?
把基于所有平台(windows/Linux/MacOS)的代码都实现一遍条件编译 动态裁剪 在什么机器上跑 就用对应的封装
对显示器的认识
在Linux中,一切皆文件的原则是指Linux将所有的资源都视为文件或文件类型的一种。这包括硬件设备、目录、文件、进程、套接字等等。在Linux中,每个文件都有一个唯一的文件描述符,它是一个非负整数,用于标识打开的文件。通过文件描述符,我们可以对文件进行读写等操作。这种一切皆文件的设计理念使得Linux系统的操作变得非常简单和统一,因为所有的资源都可以通过相同的方式进行访问和操作。同时,这种设计理念也为Linux系统提供了很好的可扩展性和灵活性,因为新的设备和资源可以很容易地被添加到系统中,并且可以通过相同的方式进行管理和访问。
举个例子,如果你想要查看CPU的温度,你可以在Linux中打开一个文件,该文件位于/sys/class/thermal/thermal_zone0/temp,然后读取该文件的内容,就可以得到CPU的温度信息。这个文件就是一个虚拟文件,它代表了CPU的温度传感器,通过读取该文件的内容,我们就可以获取到CPU的温度信息。
另外,Linux中的文件类型也非常丰富,包括普通文件、目录文件、字符设备文件、块设备文件、套接字文件等等。每种文件类型都有自己的特点和用途,例如普通文件用于存储文本、二进制数据等,目录文件用于存储其他文件和目录等。理解Linux中的文件类型对于正确地使用和管理Linux系统非常重要。
如何理解文件?
write
scanf/cin从键盘获取数据 实际上就是一种read
至于为什么从键盘输入的内容能显示到显示器上 这实际上是一种回显 这些调用库函数实现对文件的读写操作 是站在程序的角度 而程序要想能够执行这些操作 首先他得运行成为进程 即代码和数据加载到内存 即以上这些过程 是站在内存的角度 通过进程来完成的mode的不同作用和目的
r: 为了读打开一个文件 文件流定位在文件首 原文件不存在则报错
w: 为了写打开一个文件 清空文件原有内容 文件不存在创建一个新文件 文件流定位在文件首
a: 为了追加打开一个文件 文件不存在创建一个新文件 文件流定位在文件尾
(r+ w+ a+ : 为了读和写打开文件 其他对应一致)
w/a 打开不存在的文件时 会创建一个新文件 这个文件创建在哪里?
谁创建的?
源代码对应的可执行程序运行起来成为进程后进程调用系统接口创建的 ==> OS创建的!
ls /proc/pid -l
.会显示什么?
当前路径指的是什么?
. 一个进程运行时 当前所处的工作路径
#include <stdio.h>
int fputc(int c, FILE *stream);
int fputs(const char *s, FILE *stream);
int putc(int c, FILE *stream);
int putchar(int c);
int puts(const char *s);
#include <stdio.h>
int fgetc(FILE *stream);
char *fgets(char *s, int size, FILE *stream);
int getc(FILE *stream);
int getchar(void);
char *gets(char *s);
int ungetc(int c, FILE *stream);
那文件里的字符串没有\0读的时候怎么分辨?\n怎么分辨?
读是用语言读的 语言级别上读的时候识别到后加上就行了 这就是系统与语言的区别
命令行下模拟w操作
echo hello txt > test.txt//向文件写内容
.
> test.txt//输出重定向: 先打开文件 清空内容 又什么都不写 模拟完成
.
实际上 echo命令 底层就是C语言调用fopen函数执行w操作完成的
按行读取
char *fgets(char *s, int size, FILE *stream);
会自动在读到的字符串尾部+\0
C语言程序执行后三个标准输入输出流
FILE* : 把硬件看成了文件
extern FILE *stdin; --键盘
extern FILE *stdout; --显示器
extern FILE *stderr; --显示器
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("argv error!\n");
return 1;
}
//FILE* fopen(const char* path, const char* mode);
FILE* fp = fopen(argv[1], "r"); /* ./myfile test.txt */
//./mycat log.txt 模拟实现输出文件内容
if(fp == NULL)
{
perror("fopen");
return 2;
}
//按行读取
char line[64];
//char* fgets(char* s, int size, FILE * stream);
// fgetstring -- fgets 自动在所读取的字符结尾添加\0
while(fgets(line, sizeof(line), fp) != NULL)
{
//printf("%s", line);
fprintf(stdout, "%s", line);
}
//文件操作
//size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE* stream);
//const char *s1 = "hello file\n";
//fwrite(s1, strlen(s1), 1, fp);
//const char *s2 = "hello fprintf\n";
//fprintf(fp, "%s", s2);
//const char *s3 = "hello fputs\n";
//fputs(s3, fp); int fputs(const char *s, FILE *stream);
fclose(fp);
return 0;
}
C库函数: fopen fclose fread fwrite
系统接口: open close read write
应用层上一个简单的动作,在系统接口层面/OS层面,要做非常多的操作
//用比特位 标识状态
#define ONE 0x1 //0000 0001
#define TWO 0x2 //0000 0010
#define THREE 0x4 //0000 0100
void show(int flags)
{
if(flags & ONE) //0000 0001
printf("hello one\n");
if(flags & TWO) //0000 0010
printf("hello two\n");
if(flags & THREE) //0000 0100
printf("hello three\n");
}
int main()
{
show(ONE); //000 0001
printf("-----------------------------------------\n");
show(TWO); //0000 0010
printf("-----------------------------------------\n");
show(ONE | TWO); //000 0001 | 0000 0010 == 0000 0011
printf("-----------------------------------------\n");
show(ONE | THREE);
printf("-----------------------------------------\n");
show(ONE | TWO | THREE); //000 0001 | 0000 0010 | 0000 0100 == 0000 0111
printf("-----------------------------------------\n");
return 0;
}
fd: file descriptor 文件描述符 为什么创建一个文件从3开始? 0 1 2 呢?
OS内部为管理每一个被打开的文件 为每一个被打开的文件构建一个file结构体对象 充当被打开的文件 然后把这些文件对象用双链表组织起来
struct FILE
{
struct file* prev;
struct file* next;
//包含一个被打开的文件的几乎所有内容(权限,缓冲区,链接信息,属性等)
}
int main()
{
//int open(const char* pathname, int flags, mode_t mode);
//不被系统的umask掩码影响 设置umask掩码为0 (就近)
//目的是调用open()接口时 传的mode直接作为文件的权限
umask(0);
//只读
// int fd = open("log.txt", O_RDONLY);
//只写 目标文件不存在需创建新文件 每次打开清空原有内容 fopen("log.txt", "w");
//int fd = open("log.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666); //rw-rw-rw-
//if(fd < 0)
//{
// perror("open");
// return 1;
//}
//char buffer[64];
//memset(buffer, '\0', sizeof(buffer));
//
// fread()调用read时会执行一个操作:
// 在所读到的字符串结尾 + \0
// 而系统接口read()不会 read是按字节数读的
// 所以将buf数组全部置成\0 可以使得读完后最后有一个\0
//
//read(fd, buffer, sizeof(buffer)); //ssize_t read(int fd, void *buf, size_t count);
//printf("%s", buffer);
//const char *s = "hello write\n";
//const char *s = "hi\n";
//write(fd, s, strlen(s)); //ssize_t write(int fd, const void *buf, size_t count);
//只写 目标文件不存在需创建新文件 追加写入 fopen("log.txt", "a");
int fd1 = open("log1.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
printf("open success, fd: %d\n", fd1);
int fd2 = open("log2.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
printf("open success, fd: %d\n", fd2);
int fd3 = open("log3.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
printf("open success, fd: %d\n", fd3);
int fd4 = open("log4.txt", O_WRONLY | O_CREAT | O_APPEND, 0666);
printf("open success, fd: %d\n", fd4);
close(fd1);
close(fd2);
close(fd3);
close(fd4);
return 0;
}
int main()
{
char input[16] = { 0 };
ssize_t s = read(0, input, sizeof(input));
if (s > 0)
{
input[s] = '\0';
printf("%s\n", input);
}
int a = 0;
fscanf(stdin, "%d", &a); //scanf
fprintf(stdout, "%d\n", a); //printf
//ssize_t write(int fd, const void *buf, size_t count);
const char* s = "hello stdout(1)\n";
write(1, s, strlen(s));
return 0;
}