文件IO笔记

                                                                                                                                                                                       +regular ,普通文件(可执行程序)  ls -l后 以-开头
dir, 目录文件
link 链接文件
pipe,管道文件 ,进程间通信
block 块设备
char 字符设备
套接字文件(网路通信)

文件IO:系统Io(操作系统提供的open()和read()还有write())和标准Io(标准C库比如printf()和scanf())   标准IO底层还是系统IO,通过封装使其更方便 效率更高,且没有系统那么混乱


linux 和unix 称为POSIX可移植操作系统(即系统IO中的open等可移植到别的系统使用)


linux中的man命令 分9章:1章(man 1)shell命令,2章(man 2)系统调用函数,3章(man 3)  ,6章(man 6)游戏

下面我们来逐一对系统 IO 函数和标准 IO 函数中最重要最常用的接口进行详细剖析, 理解他们的异同,以便于在程序中恰当地使用他们。
<1>
open函数
//printf()的返回值是是字符int printf(const char *format,...)是一个变参函数
int open(const char *pathname,int flags);//open("1.txt")  /aaoid/asiu等路径放在1.txt中1前面位置的位置
具体代码实例

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{

int fd=open(./1.txt,O_RDWR);
if(-1==fd)//防止漏写等号
{
perror("open 1.txt failed");//打印标准出错函数
return -1;
}
printf("%d\n",fd);//看返回值(文件位置下标)
return 0;
//关闭
close(fd);
}
//宏定义的作用:给变量起别名 #difine io 1000;
文件描述符

read()函数
ssize_t read(int fd, void *buf, size_t count);//其中size_t是定义的类型(为整型)
参数解释
fd:从文件fd 中读数据
buf:指向存放读到的数据的缓冲区(给地址)
count:想要从文件 fd 中读取的字节数(buf长度)
具体代码实例

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
//打开和创建open()
int fd=open(./1.txt,O_RDWR);
if(-1==fd)//防止漏写等号
{
perror("open 1.txt failed");//打印标准出错函数
return -1;
}
//读read()
char buf[128];
read(fd,buf,sizeof(buf));
printf("%s\n",buf);//显示出buf里的内容
printf("%d\n",fd);//看返回值(文件位置下标)

//关闭
close(fd);
return 0;

}
程序:指令的集合
进程:运行的程序过程(系统调度过程);进程是一个分配资源的最小单位

线程:程序运行起来成 进程 就有一个结构体task_struct的虚拟内存,这个结构体里就包含了一套完整的资源(如:文件IO,信号,空间等等), 线程 的名字叫任务结构体是资源调度的最小单位,线程存在于内存.

ps -ef 命令查看linux进程
0号进程是所有进程的祖先(大多数进进程的祖先是init和thread)//ps -ef 命令中的PPID是父进程 PID是进程.
一个父进程可以产生多个子进程 
进程被创建出来就是就续态

进程有就续态,睡眠态/挂起态,暂停态,执行态,僵尸态
睡眠态一般是申请软件资源 而挂起态一般是硬件资源只能有特定的按键唤醒
线程是有进程创建,但是进程和线程共用内核资源
创建进程代码:
#include <unistd.h>
#include <stdio.h>

int main()
{
printf("hello \n");
pid_t  pid=fork();//创建子进程
if(pid==0)
printf("我是son");
if(pid>0)
{sleep(1);//waitpid();也可以
printf("我是你爹");
}
printf("world\n");


return 0;
}


//getpid()获得进程号
getppid()获得父进程号

//退出的函数exit(); _exit();Exit(); //退出(结束)进程的函数
函数的退出return //从函数中推出
线程退出pthread_exit()//结束线程
exit();//在退出之前,检查有没有注册退出处理函数,如果没有,会调用退出处理函数;如果有会调用处理函数,并检查IO缓冲区有没有数据,如果有局直接打印
_exit();//直接退出,什么都不管,慎用


execl("./a.out","./a.out","1.txt",NULL)以中间开始,以NULL结束
功能:在进程中加载新的程序文件或脚本,覆盖原有的代码,重新运行
头文件#include <unistd.h>
原型有六中其中int execl(const char *path, const char *arg,....,NULL)最常用
const char *path新的代码或者脚本自己本身(编译后的可执行文件),const char *arg,...NULL是新的代码或者脚本的路径或者文件名一般以文件本身开始,以NULL结束.

其它五种原型分别如下:

int execv(const char *path, char *const argv[ ]);
int execle(const char *path, const char *arg, ..., char * const envp[ ]);

int execlp(const char *file, const char *arg, ...);
int execvp(const char *file, char *const argv[ ]);
int execvpe(const char *file, char *const argv[ ],char *const envp[ ]);

参数的含义:path:即将被加载执行的ELF文件或者脚本路径
file:即将被加载的执行的ELF文件或脚本的名字
arg 以列表方式罗列的ELF文件或脚本的参数
argv 以数组方式组织的ELF文件或者脚本的参数
envp用户自定义的环境变量数组

示例代码:(说明:文件main里的son是指son.c编译后的可执行代码)

代码文件名son.c
#include <stdio.h>
#include <stdlib.h>
int main(viod)
{
printf("[%d]:yep,I am the child\n",(int)getpid());
exit(0);

}

代码文件名main
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc,int **argv)
{
pid_t x;
x=fork();
if(x>0)
{
printf("[%d]: I am the parent\n",(int)getpid());
exit(0);

}
if(x==0)
{
printf("[%d]:I am the child\n",(int)getpid());
execl("./son","./son",NULL);
printf("NEVER be printed\n");//这是一条被覆盖的代码

}
return 0;

}
下面是执行结果:
vincent@ubuntu:~/ch05/5.2$ ./exec
[24585]:I am the parent
vincent@ubuntu:~/ch05/5.2$ [24586]:I am the child
[24586]:yep, Iamthechild


5.3进程的语言
kill -l 查看信号列表
shell命令中的kill发送信号SIGKILL信号与SIGSTOP信号是无法杀死的分别是9号和19号 列子:kill -9 进程号//杀死该进程,其中9也可以是信号的名称SIGKILL

进程间的通信(IPC)方式,总归起来哟如下几种:
1,无名管道(PIPE)和有名管道(FIFO).管   
2.信号:实时信号和非实时信号(可信号嵌套)
3,system V-IPC之共享内存.系统5, 上古unix

4,system V-IPC消息队列.增强型有名管道
系统5的IPC对象ID=key
用ipcs的shell命令查看消息队列
[ipcrm  -Q key值]还有[ipcrm -q id]的shell命令来关已经创建消息队列
msgflg消息队列的标识符

5,system V-IPC之信号量.控制
p操作:资源-1
v操作:资源+1


6,套接字.


write()和read()中有阻塞等待
具体规则:
SIGPIPE 管道损毁


sudo -s是进入管理员权限下运行其它命令(输入命令后还得输入密码)

cd -回到上一次操作的目录

permission denied 权限不够报错

memccpy(buf,"字符串1","字符串2",长度);把字符串2里的字符按给的长度加到字符串1中

unlink(文件名);删除文件函数

access(path,mode);判断文件是否存在

path文件路径 mode有R_OK,W_OK,X_OK,F_OK

R_OK可读,W_OK可写,X_OK可执行,F_OK是否存在

ctime();获取当前文件的时间

在不同的终端打开同一个代码,得到的进程号是不一样的
kill -l的shell查看信号
111.strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1<str2,则返回负数;若str1>str2,则返回正数。 [1-2]
中文名strcmp外文名strcmp类    
别库函数功    能比较字符串s1和s2头文件string.h一般形式strcmp(字符串1,字符串2)

创建管道文件的写端步骤如下
1.头文件
2.判断文件是否存在,如果不存在,mkfifo()就创建有名管道文件,用access();函数判断
3.打开管道文件open()
4.用while()往管道文件里写东西,键入fgets();write();
定好退出条件,
5.关闭打开的管道文件close()

总结:进程间资源是独立的

管道:有名管道mkfifo(),具有写入原子性 多个进程可以写
无名管道:仅用于亲缘间,不能打开,半双工,不能lseek定位 一对一通信

系统V   IPC对象
消息队列  本质是增强型有名管道 把消息加入表示 就可以实现选择性读取
共享内存  读取效率高 读取写入不惧有原子性,数据践踏
信号量     p操作 v操作控制共享内存,一种元素可携带多种资源


POSIX信号量(精简版的信号量)一种元素只能携带一种资源 它用到的库不在标准c库
也不在系统库 而是在线程库里
有名信号量用于进程间
无名信号量用于线程间
-lpthread 当需要的库在线程库时加 比如线程库(gcc时加)
查看创建的信号文件的路径 /dev/shm


线程:
线程的属性:接合属性(子线程结束后父线程会接收退储和资源值);
分离属性是结束后直接退出

printf("%s",strerror(errno));
printf();是行打印
fprintf(stderr,"%c",'A');是单个打印,且打印的字符用单引号


线程运行的优先级:
1.静态优先级:0~99
其中0最低 99最高
动态优先级:-20~19  nice越低则执行的越多
默认静态优先级为0

调度策略:(1)当静态优先级相同为0时用进态优先级调度法(other)来平衡
(2)RR轮转1~99先执行优先级高的,但是在同一优先级则是轮转
(3)FIFO管道1~99先执行优先级高的,但是在同一优先级则是管道

cpu的亲和度:
把需要长期占用cpu的程序把动态优先级调低
把不需要长期占用cpu的程序的动态优先级调高

线程实际上是应用层的概念,在linux内核中,所有的调度实体都被称为任务(task),
TM之间的区别是:有些任务自己拥有一套完整的资源,而有些任务彼此之间共享一套资源.
一个标准进程,他拥有自己的一套完整的资源,包括内存空间,文件,信号的挂起队列等等,这些资源全部由PCB(即内核结构体 task_struct)统一管理,这整一套数据结构,以及他们的动态变化就是一个进程.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值