优化了命名
This commit is contained in:
327
C13-Linux系统编程/C13-Linux系统编程学习笔记.md
Normal file
327
C13-Linux系统编程/C13-Linux系统编程学习笔记.md
Normal file
@@ -0,0 +1,327 @@
|
||||
# I/O操作
|
||||
|
||||
输入输出是一切实现的基础。
|
||||
|
||||
标准IO:`stdio`
|
||||
|
||||
系统调用IO(文件IO):`sysio`
|
||||
|
||||
优先使用标准IO,兼容性更好,还有合并系统调用的优势。
|
||||
|
||||
## 标准IO
|
||||
|
||||
```c
|
||||
/* stdio */
|
||||
/* FILE类型贯穿始终 */
|
||||
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
/**
|
||||
* fopen 返回指针的储存位置? 1.栈 2.静态区 3.堆
|
||||
* 正确答案:3.堆。
|
||||
* 因为如果是栈,就是函数内部局部变量,无法返回地址。
|
||||
* 如果是静态区,无法确定需要多少个这个变量。
|
||||
*
|
||||
* 只有 r 和 r+ 一定要求文件存在
|
||||
* 另外几种不存在会创建
|
||||
*
|
||||
* 创建文件的权限
|
||||
* 0666 & ~umask
|
||||
*
|
||||
* 对于普通用户
|
||||
* umask 得到 022
|
||||
*
|
||||
*/
|
||||
int fclose(FILE *fp);
|
||||
|
||||
int fputc(FILE *stream);
|
||||
int fgetc(int c, FILE *stream);
|
||||
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
/**
|
||||
* 两种正常返回的情况:
|
||||
* 1. 读了 size-1 个字节,最后一个字节留给 '\0'
|
||||
* 2. 读到了 '\n'
|
||||
*
|
||||
* eg. 加入用fgets(buf, 5, stream) 来读 abcd
|
||||
* 是会读两次的
|
||||
* 第一次:abcd'\0'
|
||||
* 第二次:'\n''\0'
|
||||
*/
|
||||
int fputs(const char *restrict s, FILE *restrict stream);
|
||||
|
||||
/**
|
||||
* 这一对函数常用但是无法验证边界
|
||||
* 尽量一次只读单字节,更安全
|
||||
*
|
||||
* 返回值:成功读/写的对象的数量
|
||||
*/
|
||||
size_t fread(void *ptr, size_t size, size_t nemmb, FILE *stream);
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
|
||||
|
||||
int printf(const char *restrict format, ...);
|
||||
/**
|
||||
* 常用于 fprintf(stderr,...)
|
||||
*/
|
||||
int fprintf(FILE *restrict stream, const char *restrict format, ...);
|
||||
|
||||
// TODO:
|
||||
int dprintf(int fd, const char *restrict format, ...);
|
||||
|
||||
/**
|
||||
* 将格式化内容输出到一个字符串
|
||||
*
|
||||
* 和 atoi() 正好相反
|
||||
*
|
||||
*/
|
||||
int sprintf(char *restrict str, const char *restrict format, ...);
|
||||
|
||||
/**
|
||||
* 比sprintf多了size参数,更安全
|
||||
*/
|
||||
int snprintf(char str[restrict.size],
|
||||
size_t size,
|
||||
const char *restrict format,
|
||||
...)
|
||||
|
||||
// !!! 慎用%s
|
||||
int scanf(const char *restrict format, ...);
|
||||
int fscanf(FILE *restrict stream,
|
||||
const char *restrict format, ...);
|
||||
|
||||
|
||||
/**
|
||||
* 移动文件当前位置指针
|
||||
*
|
||||
* 可用于生成空洞文件,下载器原理
|
||||
*
|
||||
* @prarm: offset 移动多远
|
||||
* @prarm: whence 移动方向
|
||||
* SEEK_SET, SEEK_CUR, SEEK_END
|
||||
*
|
||||
* @return 成功0,失败-1
|
||||
*/
|
||||
int fseek(FILE *stream, long offset, int whence);
|
||||
|
||||
/**
|
||||
* 反映当前文件指针所在位置
|
||||
*
|
||||
* 这个long的负值部分无法使用。
|
||||
* 所以文件无法超过2G。
|
||||
*
|
||||
*/
|
||||
long ftell(FILE *stream);
|
||||
|
||||
/**
|
||||
* 解决上面long的问题。
|
||||
*
|
||||
* 最好编译时加上
|
||||
* #define _FILE_OFFSET_BITS 64
|
||||
* 可以写入makefile
|
||||
*
|
||||
* 但是这俩函数是方言,前面那个long的一对支持C89,C99
|
||||
*
|
||||
*/
|
||||
int fseeko(FILE *stream, off_t offset, int whence);
|
||||
off_t ftello(FILE *stream);
|
||||
|
||||
/**
|
||||
* 将文件指针置于文件首
|
||||
* equivalent to:
|
||||
* fseek(stream, 0L, SEEK_SET);
|
||||
*/
|
||||
void rewind(FILE *stream);
|
||||
|
||||
/**
|
||||
* 缓冲区的作用:
|
||||
* 大多数情况下是好事,合并系统调用
|
||||
*
|
||||
* 行缓冲: 换行时候刷新,满了的时候刷新,强制刷新(标准输出是这样的,因为是终端设备)
|
||||
*
|
||||
* 全缓冲: 满了的时候刷新,强制刷新(默认,只要不是终端设备)
|
||||
*
|
||||
* 无缓冲: 如stderr,需要立即输出的内容
|
||||
*/
|
||||
fflush();
|
||||
|
||||
/**
|
||||
* @prarm: mode
|
||||
* _IONBF
|
||||
* _IOLBF
|
||||
* _IOFBF
|
||||
*/
|
||||
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
|
||||
|
||||
/**
|
||||
* 为了读取一行
|
||||
*
|
||||
* 使用办法:
|
||||
* #define _GNU_SOURCE 这个不想写到代码里面的话可以写到makefile
|
||||
* eg. CFLAGS+=-D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
* #include <stdio.h>
|
||||
*
|
||||
* !!! 里面有 malloc 动作,未释放
|
||||
* !!! 是方言,可以自己封装一个mygetline和mygetline_free
|
||||
*
|
||||
*/
|
||||
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
|
||||
|
||||
/**
|
||||
* 临时文件
|
||||
* 1. 如何不冲突的创建
|
||||
* 2. 及时销毁
|
||||
*
|
||||
* tmpnam: 创建临时文件名字
|
||||
* 有并发危险,因为产生名字和创建文件是两步
|
||||
*
|
||||
* tmpfile: 创建临时文件
|
||||
* 是匿名文件,ls -a 都看不到
|
||||
* 避免冲突
|
||||
*/
|
||||
char *tmpnam(char *s);
|
||||
FILE *tmpfile(void);
|
||||
|
||||
```
|
||||
|
||||
|
||||
## 文件IO/系统调用IO
|
||||
|
||||
文件描述符(`fd`)是在文件IO中贯穿始终的类型。
|
||||
|
||||
### 文件描述符的概念
|
||||
是一个整型数,是一个指针数组的下标。
|
||||
优先使用当前可用范围内最小的。
|
||||
|
||||
### 文件IO操作相关函数:
|
||||
- open
|
||||
- close
|
||||
- read
|
||||
- write
|
||||
- lsee
|
||||
|
||||
```c
|
||||
|
||||
/**
|
||||
* r -> O_RDONLY
|
||||
* r+ -> O_RDWR
|
||||
* w -> O_WRONLY | O_CREAT | O_TRUNC
|
||||
* w+ -> O_RDWR | O_TRUNC | O_CREAT
|
||||
*
|
||||
* 如果有creat就必须用三参数的形式
|
||||
* C语言没有重载,这是变参函数
|
||||
*
|
||||
* @prarm: pathname 文件路径
|
||||
* @prarm: flags 文件打开方式
|
||||
* @prarm: mode 文件权限
|
||||
*
|
||||
*/
|
||||
int open(const char *pathname, int flags);
|
||||
int open(const char *pathname, int flags, mode_t mode);
|
||||
|
||||
int close(int fd);
|
||||
|
||||
/**
|
||||
* read from a file descriptor
|
||||
*
|
||||
* @return 读取的字节数,失败返回-1
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* write to a file descriptor
|
||||
*
|
||||
* @return 写入的字节数,失败返回-1
|
||||
*/
|
||||
ssize_t write(int fd, const void *buf, size_t count);
|
||||
|
||||
/**
|
||||
* 移动文件指针
|
||||
*
|
||||
* @prarm: offset 移动多远
|
||||
* @prarm: whence 移动方向
|
||||
* SEEK_SET, SEEK_CUR, SEEK_END
|
||||
*
|
||||
* @return 成功0,失败-1
|
||||
*/
|
||||
off_t lseek(int fd, offt offset, int whence);
|
||||
|
||||
```
|
||||
|
||||
|
||||
### 文件IO与标准IO的区别
|
||||
区别:响应速度&吞吐量
|
||||
文件IO需要频繁进入内核,标准IO通过缓冲区合并系统调用。
|
||||
响应速度快就文件IO,吞吐量大就标准IO。
|
||||
> [!warning]
|
||||
> 二者不可混用
|
||||
|
||||
转换方法:`fileno`, `fdopen`
|
||||
|
||||
### IO的效率问题
|
||||
习题:将`mycpy.c`程序进行更改,将`BUFSIZE`的值放大,观察进程消耗的时间,注意性能出现拐点的值以及程序何时段错误。
|
||||
|
||||
### 文件共享
|
||||
多个任务共同操作一个文件或者协同完成任务
|
||||
|
||||
面试题:写程序删除一个文件的第10行
|
||||
补充函数:
|
||||
```c
|
||||
// 截断文件到某长度
|
||||
int truncate(const char *path, off_t length);
|
||||
int ftruncate(int fd, off_t length);
|
||||
```
|
||||
|
||||
```c
|
||||
// 最简单思路,将11行开始的内容到第10行开始处覆盖写
|
||||
while()
|
||||
{
|
||||
lseek 11 + read +lseek 10 + write
|
||||
}
|
||||
|
||||
// 优化思路,两个文件描述符,一个读一个写
|
||||
1 -> open r -> fd1 -> lseek 11
|
||||
2 -> open r+ -> fd2 -> lseek 10
|
||||
|
||||
while()
|
||||
{
|
||||
1->fd1-> read
|
||||
2->fd2-> write
|
||||
}
|
||||
|
||||
// 两个进程, 设计进程间通信
|
||||
process1 -> open -> r
|
||||
process2 -> open -> r+
|
||||
|
||||
p1->read -> p2->write
|
||||
|
||||
```
|
||||
|
||||
### 原子操作
|
||||
指不可分割的操作
|
||||
作用:解决竞争和冲突
|
||||
如`tmpnam`函数,产生文件名和创建文件是两步,会有并发问题。
|
||||
|
||||
|
||||
### 程序中的重定向:`dup`, `dup2`
|
||||
```c
|
||||
int dup(int oldfd);
|
||||
int dup2(int oldfd, int newfd);
|
||||
```
|
||||
|
||||
### 同步
|
||||
同步内核层面的buffer和cache
|
||||
```c
|
||||
void sync(void);
|
||||
int fsync(int fd);
|
||||
int fdatasync(int fd); // 只刷新数据,不刷新亚数据
|
||||
|
||||
// 文件描述符所有的操作几乎都来源于该函数
|
||||
int fcntl(int fd, int cmd, ... /* arg */);
|
||||
|
||||
// 设备相关的内容
|
||||
int ioctl(int fd, unsigned long request, ... /* arg */);
|
||||
|
||||
```
|
||||
|
||||
### /dev/fd/目录
|
||||
**虚目录**:显示当前进程的文件描述符信息
|
||||
52
C13-Linux系统编程/C13-Linux系统编程项目实战.md
Normal file
52
C13-Linux系统编程/C13-Linux系统编程项目实战.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# 项目前瞻
|
||||
|
||||
基于IPV4的流媒体广播系统。
|
||||
|
||||
|
||||
|
||||
## 项目需求
|
||||
|
||||
需要基于客户机和服务器模型的网络音频广播/点播系统。
|
||||
|
||||
用于语音教室和公共广播。
|
||||
|
||||
分为服务器和客户机,服务器在PC上运行,客户机在PC机或者嵌入式设备。
|
||||
|
||||
服务器可以向局域网内以多播的方式给所有客户机发送数据,客户机自己选择接收数据。
|
||||
|
||||
|
||||
|
||||
## 简要框图
|
||||
|
||||
<img src="https://s2.loli.net/2024/04/25/kpolhzmgBEcSYxM.png"/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 参考书目
|
||||
|
||||
1. UNIX环境高级编程(第一版经典,第二版有错误)
|
||||
2. UNIX网络编程
|
||||
3. TCP/IP详解(卷一)
|
||||
4. 深入理解计算机系统
|
||||
|
||||
|
||||
|
||||
## 知识网络
|
||||
|
||||
- I/O操作(参考书目1:3,5章,14章非阻塞IO)
|
||||
- 文件系统(参考书目1:4,6,7章)
|
||||
- 并发(信号10章,多线程10,11章)
|
||||
- IPC(进程间通信,8章进程基础,13章守护进程)
|
||||
- 进程间通信(15,16章)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 弃用root用户
|
||||
2. 重构
|
||||
3. 课堂重点:项目,课堂代码,面试题,实验性题目,推荐书籍的课后题
|
||||
1
C13-Linux系统编程/io/stdio/Makefile
Normal file
1
C13-Linux系统编程/io/stdio/Makefile
Normal file
@@ -0,0 +1 @@
|
||||
CFLAGS+=-D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
|
||||
28
C13-Linux系统编程/io/stdio/atoi.c
Normal file
28
C13-Linux系统编程/io/stdio/atoi.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[1024];
|
||||
int year = 2014, month = 5, day = 13;
|
||||
|
||||
printf("%d-%d-%d\n", year, month, day);
|
||||
|
||||
sprintf(buf, "%d-%d-%d", year, month, day);
|
||||
puts(buf);
|
||||
|
||||
#if 0
|
||||
char str[] = "123456";
|
||||
|
||||
printf("%d\n", atoi(str));
|
||||
/**
|
||||
* 输出 123456
|
||||
*
|
||||
* 如果str是123a456
|
||||
* 输出123
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
exit(0);
|
||||
}
|
||||
20
C13-Linux系统编程/io/stdio/fflush.c
Normal file
20
C13-Linux系统编程/io/stdio/fflush.c
Normal file
@@ -0,0 +1,20 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
// 这里不加\n的话,什么都不输出
|
||||
// 要么加\n,要么fflush
|
||||
printf("Before while()");
|
||||
fflush(stdout);
|
||||
|
||||
while (1)
|
||||
;
|
||||
|
||||
printf("After while()");
|
||||
fflush(NULL);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
32
C13-Linux系统编程/io/stdio/fgetc.c
Normal file
32
C13-Linux系统编程/io/stdio/fgetc.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
int count;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (EOF != fgetc(fp))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
|
||||
printf("count = %d", count);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
28
C13-Linux系统编程/io/stdio/flen.c
Normal file
28
C13-Linux系统编程/io/stdio/flen.c
Normal file
@@ -0,0 +1,28 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
|
||||
printf("%d\n", ftell(fp));
|
||||
|
||||
fclose(fp);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
31
C13-Linux系统编程/io/stdio/fopen.c
Normal file
31
C13-Linux系统编程/io/stdio/fopen.c
Normal file
@@ -0,0 +1,31 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp = fopen("tmp", "r");
|
||||
if (NULL == fp)
|
||||
{
|
||||
// fprintf(stderr, "fopen() failed! errno = %d\n", errno);
|
||||
// out: fopen() failed! errno = 2
|
||||
/* errno:定义路径 /usr/include/asm-generic/errno-base.h */
|
||||
|
||||
// perror("fopen()");
|
||||
// out: fopen(): No such file or directory
|
||||
|
||||
fprintf(stderr, "fopen(): %s\n", strerror(errno));
|
||||
// out: fopen(): No such file or directory
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
puts("OK!");
|
||||
|
||||
fclose(fp);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
40
C13-Linux系统编程/io/stdio/getline.c
Normal file
40
C13-Linux系统编程/io/stdio/getline.c
Normal file
@@ -0,0 +1,40 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fp;
|
||||
char *linebuf;
|
||||
size_t linesize;
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
fprintf(stderr, "Usage...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fp = fopen(argv[1], "r");
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// !!!
|
||||
linebuf = NULL;
|
||||
linesize = 0;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (getline(&linebuf, &linesize, fp) < 0)
|
||||
break;
|
||||
printf("%d\n", strlen(linebuf));
|
||||
printf("%d\n", linesize);
|
||||
// 此时输出linesize值不对,是因为没有初始化
|
||||
// 修改后发现,linesize初始值就是120,是后面不够再增加
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
exit(0);
|
||||
}
|
||||
32
C13-Linux系统编程/io/stdio/maxfopen.c
Normal file
32
C13-Linux系统编程/io/stdio/maxfopen.c
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
int count = 0;
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
fp = fopen("tmp", "w");
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen()");
|
||||
break;
|
||||
}
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
printf("count = %d\n", count);
|
||||
// out: 4089
|
||||
/* 可以通过下面这个命令限制 */
|
||||
/* ulimit -n */
|
||||
/* 4096 */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
51
C13-Linux系统编程/io/stdio/mycpy.c
Normal file
51
C13-Linux系统编程/io/stdio/mycpy.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @details
|
||||
* usage: ./mycpy <src> <dst>
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fps, *fpd;
|
||||
int ch;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage:%s <src> <dst>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[1], "r");
|
||||
if (NULL == fps)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[2], "w");
|
||||
if (NULL == fpd)
|
||||
{
|
||||
// !!!
|
||||
fclose(fps);
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
ch = fgetc(fps);
|
||||
if (EOF == ch)
|
||||
break;
|
||||
fputc(ch, fpd);
|
||||
}
|
||||
|
||||
fclose(fpd);
|
||||
fclose(fps);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
48
C13-Linux系统编程/io/stdio/mycpy_fgets.c
Normal file
48
C13-Linux系统编程/io/stdio/mycpy_fgets.c
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @details
|
||||
* usage: ./mycpy <src> <dst>
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fps, *fpd;
|
||||
char buf[BUFSIZE];
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage:%s <src> <dst>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[1], "r");
|
||||
if (NULL == fps)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[2], "w");
|
||||
if (NULL == fpd)
|
||||
{
|
||||
// !!!
|
||||
fclose(fps);
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (NULL != fgets(buf, BUFSIZE, fps))
|
||||
fputs(buf, fpd);
|
||||
|
||||
fclose(fpd);
|
||||
fclose(fps);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
50
C13-Linux系统编程/io/stdio/mycpy_fread.c
Normal file
50
C13-Linux系统编程/io/stdio/mycpy_fread.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define BUFSIZE 1024
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* @details
|
||||
* usage: ./mycpy <src> <dst>
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fps, *fpd;
|
||||
char buf[BUFSIZE];
|
||||
int n;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage:%s <src> <dst>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[1], "r");
|
||||
if (NULL == fps)
|
||||
{
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fopen(argv[2], "w");
|
||||
if (NULL == fpd)
|
||||
{
|
||||
// !!!
|
||||
fclose(fps);
|
||||
perror("fopen()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* 用n接收读到的个数,因为不知道能不能正好读到BUFSIZE */
|
||||
while ((n = fread(buf, 1, BUFSIZE, fps)) > 0)
|
||||
fread(buf, 1, n, fpd);
|
||||
|
||||
fclose(fpd);
|
||||
fclose(fps);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
27
C13-Linux系统编程/io/sys/ab.c
Normal file
27
C13-Linux系统编程/io/sys/ab.c
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
putchar('a');
|
||||
write(1, "b", 1);
|
||||
|
||||
putchar('a');
|
||||
write(1, "b", 1);
|
||||
|
||||
putchar('a');
|
||||
write(1, "b", 1);
|
||||
|
||||
/**
|
||||
* 这里标准IO与文件IO混用
|
||||
* 实际输出:
|
||||
* bbbaaa
|
||||
*
|
||||
* 命令 strace
|
||||
* 可以跟踪系统调用
|
||||
*
|
||||
*/
|
||||
|
||||
exit(0);
|
||||
}
|
||||
51
C13-Linux系统编程/io/sys/dup.c
Normal file
51
C13-Linux系统编程/io/sys/dup.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FNAME "/tmp/out"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int fd;
|
||||
|
||||
/***
|
||||
* bug:
|
||||
* 1. 假如默认没有1,这里有bug。
|
||||
* 2. 假如这个非原子操作的操作的过程,有可能被别的进程影响。
|
||||
*/
|
||||
fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// close(1);
|
||||
// dup(fd);
|
||||
dup2(fd, 1);
|
||||
// 使用 dup2 原子操作
|
||||
// 且dup2如果两个参数相等,不会做任何事
|
||||
|
||||
// !!!
|
||||
if (1 != fd)
|
||||
close(fd);
|
||||
|
||||
#if 0
|
||||
close(1);
|
||||
|
||||
fd = open(FNAME, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (fd < 0)
|
||||
{
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/********************************************************************/
|
||||
puts("hello!");
|
||||
|
||||
// TODO: 将sdtout回到终端
|
||||
|
||||
exit(0);
|
||||
}
|
||||
71
C13-Linux系统编程/io/sys/mycpy.c
Normal file
71
C13-Linux系统编程/io/sys/mycpy.c
Normal file
@@ -0,0 +1,71 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFSIZE 1024
|
||||
/**
|
||||
* 可以用 time 命令找到 BUFSIZE 最佳值
|
||||
*
|
||||
* time ./mycpy /etc/services /tmp/out
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int sfd, dfd;
|
||||
char buf[BUFSIZE];
|
||||
int len, ret, pos;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s <src> <dst>\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sfd = open(argv[1], O_RDONLY);
|
||||
if (sfd < 0)
|
||||
{
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dfd = open(argv[2], O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
if (dfd < 0)
|
||||
{
|
||||
// !!!
|
||||
close(sfd);
|
||||
perror("open");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
len = read(sfd, buf, BUFSIZE);
|
||||
if (len < 0)
|
||||
{
|
||||
perror("read");
|
||||
break;
|
||||
}
|
||||
if (len == 0)
|
||||
break;
|
||||
|
||||
pos = 0;
|
||||
while (len > 0)
|
||||
{
|
||||
/* 可能没写完被别的中断打断 */
|
||||
ret = write(dfd, buf + pos, len);
|
||||
if (ret < 0)
|
||||
{
|
||||
perror("write");
|
||||
exit(1);
|
||||
}
|
||||
pos += ret;
|
||||
len -= ret;
|
||||
}
|
||||
}
|
||||
|
||||
close(dfd);
|
||||
close(sfd);
|
||||
|
||||
exit(0);
|
||||
}
|
||||
Reference in New Issue
Block a user