服务端
- 多线程或多进程并发
- 引入数据库或者使用当前文件系统
解析文件系统存储 - 流量控制
- 网络套接字socket
- 应为守护进程,脱离终端,IO重定向,系统日志
客户端
- 父进程,从网络上接收数据,传递给子进程
- 子进程,接收数据并播放
- 父、子进程实现及其关系
- 进程通信
参考资料
《UNIX环境高级编程(第3版)》
《UNIX网络编程》
《TCP/IP详解(卷一)》
《深入理解计算机系统》
学习方法介绍
- 纸上得来终觉浅,绝知此事要躬行
IO
第3、5章节
文件系统
第4、6、7章节
并发
第8、10、11章节
多进程并发(信号)第10章
多线程并发第10、11章节
IPC 进程间通信
进程基础(涉及多进程)第8章
守护进程 第13章
进程间通信 第15、16章节
注意事项:
- 弃用root用户
- 对代码进行
重构
- 课堂重点:项目,课堂代码,面试题,实验性题目,推荐书籍的课后习题
I/O,input & output,是一切实现的基础。
stdio 标准IO
sysio 系统调用IO(文件IO)
优先考虑标准I/O
标准IO
stdio: man 3
fopen(); 文件打开
fclose(); 文件关闭
fgetc(); 读取字符
fputc(); 写字符
fgets(); 读取字符串
fputs(); 写字符串
fread(); 读二进制
fwrite(); 写二进制
printf()族
scanf()族
fseek();
ftell();
rewind();
fflush();
标准IO相关结构体FILE
man fopen
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
参数:
pathname,文件路径名
mode,打开模式
r,只读打开,文件指针在beginning of file (不会创建)
r+,读写打开,文件指针在文件开始处 (不会创建)
w,只写形式打开,有则清空,无则创建,文件指针在文件开始处(文件的第一个有效字节)
w+,读写形式打开,有则清空,无则创建,文件指针在文件开始处(文件的第一个有效字节)
a,追加写(只有追加写,没有追加读),文件最后一个有效字节的下一个位置(end of file)
a+,以读写(追加写)形式打开文件,无则创建,
读:beginning of file,即 文件的第一个有效字节
追加写:end of file,即文件最后一个有效字节的下一个位
注意:区分文件最后一个有效字节与最后一个有效字节的下一个位置
b,二进制,Windows区分字符与二进制
注意,r和r+ 要求文件必须存在,否则结束当前调用,返回错误
返回值:
成功:FILE指针
失败:NULL,errno(errno是全局变量?)
errno定义的位置:
cat /usr/include/asm-generic/errno.h
cat /usr/include/asm-generic/errno-base.h
面试题
已知条件:
char *ptr="abc"; //字符串常量
ptr[0]='x';
问:是否会得到"xbc"?
答:取决于当前平台使用的编译器会把"abc"放到哪里存储?
编程tips
int *p = malloc(sizeof(int));
malloc的返回值是void *
如果不添加头文件#include<stdlib.h>,
gcc会认为所有函数的返回值是int(有例外),将int型赋值给int *必然会报错
补充函数perror与strerror
man perror
perror - print a system error message
man strerror
#include <string.h>
char *strerror(int errnum); //return string describing error number
打开不同的注释,观察执行结果
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int
main (){
FILE *fp;
fp= fopen("tmp","r");
if(fp==NULL){
//fprintf(stderr,"fopen error! errno= %d \n",errno);
perror("fopen()");
//fprintf(stderr,"fopen():%s\n",strerror(errno));
exit(1);
}
puts("fopen OK!");
exit(0);
}
思考:
FILE *fopen(const char *pathname, const char *mode);
调用fopen返回的FIEL结构体保存在哪里?
1. 栈?
2. 静态区?
3. 堆?
FILE *fopen(const char *pathname, const char *mode);
{
FILE tmp; //局部变量?? ❌
tmp.xx=uu;
...
return tmp;
----------------------------------------
static FILE tmp; //静态区?? ❌ 后打开的会覆盖先打开的
tmp.xx=vv;
...
return tmp;
----------------------------------------
FILE *tmp = NULL; //放在堆?? ✔
tmp = malloc (sizeof FILE); //
tmp->xx=ww;
...
return &tmp;
}
fopen fclose
//如果一个函数的返回值是指针,并且该函数有一个逆操作,通常这样的函数的返回值指针存储在堆上
函数fclose
man fclose
fclose - close a stream 关闭流
#include <stdio.h> //头文件
int fclose(FILE *stream); //函数原型
- 谁打开谁关闭
- 谁申请谁释放
- 是资源就有上限
在不更改当前默认环境的情况下,一个进程默认打开3个stream流:
可通过ulimit -a
查看,通过ulimit -n xxx
更改对应的值
- stdin
- stdout
- stderr
user@ubuntu:~/codes$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15374
max locked memory (kbytes, -l) 65536
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 15374
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
文件权限(以umask=0002为例)
0666 & ~umask
110 110 110 ---0666
000 000 010 ---0002
0666 与umask取反相与
111 111 101 ---~umask
110 110 110 ---0666
110 110 100 ---0666 & ~umask 相与的结果
即664 rw-rw-r--
lry@ubuntu:~/codes$ ll tmp
-rw-rw-r-- 1 lry lry 0 9月 30 23:16 tmp
待学习fgetc fputc。。。。。