一、IO与文件映射
1. IO的共享与效率
read与write其中数据缓冲的大小
读取数据的缓冲:getpagesize。一般用它的返回值大小设置为缓冲大小就可以,也可以为一个页大小。
2. 定位与定位读取(随机读取)
read与write在操作的时候,自动移动读取位置.
lseek改变读取位置.
pread/pwrite在指定位置读写。
ssize_t pread(intfd, void *buf, size_tcount, off_toffset);
ssize_t pwrite(intfd, const void *buf, size_tcount, off_toffset);
2.1 lseek的函数说明:
off_t lseek(
int fd, //定位文件描述符号
off_t off, //定位位置
int whence //定位参照点:SEEK_SET 文件开始位置/SEEK_END 文件结束位置/SEEK_CUR文件当前位置
);
返回:
返回当前读取位置在文件中的绝对位置.
2.2 lseek(是小写的L)的作用:定位文件的位置
问题:lseek的定位的位置超出文件的大小范围?
lseek移动位置只要合法,都是有效
2.3 lseek+write=pwrite
lseek+read =pread
2.4 案例:
读取一个特殊的文件:
/proc/${pid}/mem文件程序的虚拟内存文件
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
int a=9999;
main()
{
char filename[100];
int fd;
int data=8888;
//得到文件名
sprintf(filename,"/proc/%d/mem",getpid());
//打开文件
fd=open(filename,O_RDWR);
if(fd==-1) printf("open error:%m\n"),exit(-1);
//读取a地址这个位置的数据
//pread(fd,&data,4,(int)&a);
//lseek(fd,(int)&a,SEEK_SET);
//read(fd,&data,4);
//write(fd,&data,4);
pwrite(fd,&data,4,(int)&a);//00
printf("%d\n",a);//输出9999,这是因为在00位置程序没有写的权限
printf("%d\n",data);//输出9999
close(fd);
}
3. 文件的其他操作
fstat 获取文件状态
ftruncate 改变文件大小
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
main()
{
int fd;
struct stat st;
fd=open("stu.dat",O_RDONLY);
if(fd==-1) printf("err:%m\n"),exit(-1);
fstat(fd,&st);
printf("%d,%o\n",st.st_size,st.st_mode);
close(fd);
}
4. 文件映射:
虚拟地址映射到内存。
虚拟地址可以映射到文件:可以用内存方式访问文件.
mmap/munmap
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/mman.h>
struct stu
{
char name[20];
int age;
float score;
};
main()
{
int fd;
struct stu *s;//文件在虚拟内存的映射首地址
struct stat st;
int size;//文件大小
int count;//记录条数
int i;
//1.打开文件
fd=open("newstu.dat",O_RDWR|O_CREAT|O_EXCL,0666);
if(fd==-1)
{
fd=open("newstu.dat",O_RDWR);
if(fd==-1) printf("::%m\n"),exit(-1);
}
//2.得到文件大小,文件记录条数
fstat(fd,&st);
size=st.st_size;
count=size/sizeof(struct stu);
//3.文件大小改变只要在munmap之前调用都有效
//ftruncate(fd,size+sizeof(struct stu));
//4.映射到一个虚拟的地址
s=mmap(0,size+sizeof(struct stu),
PROT_READ|PROT_WRITE,
MAP_SHARED,fd,0);
//5.把数据写入虚拟地址
printf("输入姓名:");
scanf("%s",s[count].name);
printf("输入年龄:");
scanf("%d",&(s[count].age));
printf("输入成绩:");
scanf("%f",&(s[count].score));
ftruncate(fd,size+sizeof(struct stu));//比较好的位置
for(i=0;i<count;i++)
{
printf("%s,\t,%d,\t%.2f\n",
s[i].name,s[i].age,s[i].score);
}
//6.卸载虚拟地址
munmap(s,sizeof(struct stu)+size);
//7.关闭文件
close(fd);
}
二、文件描述符号的操作(IO锁)
文件描述符号是整数。文件描述符号对应内核的上下文环境。
1. dup dup2拷贝文件描述符号
dup 拷贝文件符号,返回系统指定的整数
dup2 拷贝文件描述符号,返回用户指定的整数
2. fcntl对文件描述的属性的修改
2.1 拷贝文件描述符号
2.2 修改判定文件的描述标记
2.3 修改判定文件的状态标记
不可修改:O_RDONLY O_WRONLY _ORDWR O_CREAT O_EXCL
可以修改:O_APPEND O_ASYN
2.4 设置强制锁(重新编译内核)
2.5 设置建议锁(默认)
2.6 设置的信号
三、IO与Curses(介绍)
Curses:CUI(字符UI)
UI:User Interface.分类
CUI:字符界面
GUI:图形界面
使用一套封装库 libcurses.so
在/usr/lib目录下
编译只需要指定-lcurses
老版本: libcurses.so
新的版本: ibncurses.so
如果头文件curses.h不存在,请尝试使用ncurses.h
如果库文件curses 不存在,请尝试使用ncurses
printf / scanf标准IO
大部分标准IO重定向到终端./dev/tty /dev/pts/1
curses就是终端输出.
-lcurses -ncurses
为了防止printf重定向到终端破坏UI,禁止在curses中使用标准IO.
1. 编程模型
初始化终端 initscr
操作终端 (输入/输出/定位/刷新....)
释放终端 endwin
2. 显示
2.1 图形输出
border
box
hline
vline
属性字符:字节 = 属性字节 + 字符字节
注意:
box需要窗体.
initscr返回被初始化的窗体:标准屏幕WINDOW*
实际上curses定义一个全局变量stdscr就是标准屏幕
函数命名规则:
**** 标准屏幕stdscr
w**** 指定窗体
mv**** 指定位置
mvw**** 指定窗体的指定位置
2.2 刷屏
void refresh()
void wrefresh(WINDOW*);
从里到外刷屏
#include <curses.h>
int main()
{
initscr();//初始化终端
//border(0,0,0,0,0,0,0,0);//默认参数
border('a','b','c','d','e','f','g','h');
box(stdscr,0,0);
mvhline(2,10,'=',20);
mvvline(2,10,'|',10);
refresh();
//wrefrsh(stdscr);
getch();//等待一个字符输入
endwin();//释放终端
return 0;
}
2.3 字符输出
addch
普通字符:''
属性字符:''|属性
特殊的属性字符:比如ACS_PI
2.4 字符串输出
int addstr(const char *);
2.5.格式字符串输出
int printw(const char*,....);
3. 字符属性与颜色
颜色属性
3.1 判定终端是否支持颜色
bool has_colors(); //都支持颜色,建议不判定
3.2 初始化颜色:
int start_color();
3.3 定义颜色对
int init_pair(short pair,short fore,short back);
3.4 使用颜色对
COLOR_PAIR(short pair)
3.5 设置属性
attron()开启属性
attroff()关闭属性
这组函数一定要在initscr后调用
3.6 背景函数:
bkgd();
#include <curses.h>
int main()
{
initscr();
if(has_colors()==TRUE)
{
start_color();
init_pair(1,COLOR_RED,COLOR_WHITE);
init_pair(2,COLOR_BLUE,COLOR_GREEN);
init_pair(3,COLOR_BLACK,COLOR_WHITE);
bkgd(COLOR_PAIR(3));
}
box(stdscr,0,0);
mvaddch(2,10,ACS_PI|COLOR_PAIR(1));
mvaddch(2,11,ACS_PI|COLOR_PAIR(2));
attron(COLOR_PAIR(1));
mvaddstr(5,10,"Hello 世界!");
attroff(COLOR_PAIR(1));
attron(COLOR_PAIR(2)|A_UNDERLINE);
mvaddstr(7,10,"Hello Fellow!");
attroff(COLOR_PAIR(2)|A_UNDERLINE);
mvprintw(9,10,"行:%d,列:%d",LINES,COLS);
getch();
endwin();
}
4. 案例:
4.1 时间显示屏幕
1.初始化
2.循环显示时间,并且睡眠1秒
3.释放
#include <curses.h>
#include <time.h>
#include <unistd.h>
void init();
void drawui();
void business();
void destroy();
main()
{
init();
drawui();
business();
destroy();
}
void business()
{
time_t tt;
struct tm *t;
while(1)
{
//取时间
tt=time(0);
t=localtime(&tt);
//显示时间
mvprintw(LINES/2,(COLS-8)/2,
"%02d:%02d:%02d",
t->tm_hour,t->tm_min,t->tm_sec);
//刷新屏幕
refresh();
sleep(1);
}
}
void drawui()
{
box(stdscr,0,0);
}
void destroy()
{
endwin();
}
void init()
{
initscr();
}
4.2 登录界面
1. 初始化
2 绘制界面
头
绘制用户名输入区
绘制密码输入区
3.等待输入
4.结束
#include <curses.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
void init();
void drawLogin();
void destroy();
main()
{
init();
drawLogin();
destroy();
}
void drawLogin()
{
char *heads="联通BSS业务支撑系统";
char *user="用户[ ]";
char *pass="口令[ ]";
box(stdscr,0,0);
attron(A_BOLD);
mvaddstr(3,(COLS-strlen(heads))/2,heads);
mvhline(4,(COLS-strlen(heads))/2,0,strlen(heads));
attroff(A_BOLD);
mvaddstr(8,(COLS-strlen(user))/2,user);
mvaddstr(10,(COLS-strlen(pass))/2,pass);
refresh();
}
void destroy()
{
getch();
endwin();
}
void init()
{
initscr();
}
5. 输入
5.1 字符输入
int getch();
返回的是字符
禁止回显noecho
使功能键有效,使用keypad(WINDOW*,bool)
#include <curses.h>
main()
{
int ch;
//初始化
initscr();
noecho();
//循环输入
while(1)
{
ch=mvgetch(5,10);
//循环显示输入
mvprintw(8,10,"你输入的是:%c(%d)",ch,ch);
}
//释放
endwin();
}
5.2 字符串输入
int addstr
5.3 格式数据输入
scanw
#include <curses.h>
main()
{
char name[9]={0};
int r;
initscr();
//绘制UI
mvaddstr(4,10,"用户:[ ]");
//输入
r=mvgetnstr(4,16,name,8);
//name[r]=0;
//打印输入
mvprintw(7,10,"你输入的是:%s",name);
refresh();
//输入字符
getch();
endwin();
}
6. 案例:
使用键盘控制字母在屏幕上的移动
补充:
curses屏幕清除:man 3 clear
clear
erase
光标控制:
得到光标位置 getsyx
设置光标的位置 setsyx
控制光标是否可见 curs_set();
#include <curses.h>
main()
{
int ch;
int x=5,y=5;
initscr();
keypad(stdscr,TRUE);
curs_set(0);
noecho();
mvaddch(y,x,'A');
while(1)
{
ch=getch();
//mvaddch(y,x,' ');
//clrtoeol();
erase();
//clear();
switch(ch)
{
case KEY_UP:
y--;
break;
case KEY_DOWN:
y++;
break;
case KEY_LEFT:
x--;
break;
case KEY_RIGHT:
x++;
break;
}
mvaddch(y,x,'A');
refresh();
}
endwin();
}
#include <curses.h>
void init();
void drawUi();
void dealInput();
void destroy();
main()
{
init();
drawUi();
dealInput();
destroy();
}
void dealInput()
{
int a,b;
while(1)
{
mvaddstr(2,3," ");
mvscanw(2,3,"%d",&a);
mvaddstr(2,11," ");
mvscanw(2,11,"%d",&b);
mvaddstr(2,19," ");
mvprintw(2,19,"%d",a+b);
refresh();
}
}
void drawUi()
{
mvaddstr(2,2,"[ ]+[ ]=[ ]");
refresh();
}
void destroy()
{
endwin();
}
void init()
{
initscr();
}
7. 窗口
subwin() //创建子窗体(坐标采用标准屏幕坐标)
derwin() //创建子窗体(坐标采用父窗体坐标)
#include <curses.h>
main()
{
WINDOW *w;
initscr();
box(stdscr,0,0);
w=derwin(stdscr,4,20,5,3);
box(w,0,0);
refresh();
wrefresh(w);
getch();
endwin();
}
一.目录管理
目录遍历
二.进程
1.进程的创建
2.进程的应用
3.进程的基本控制