7.24 open
fork复制进程
僵死进程 :子进程先于父进程结束 父进程没有获取子进程的退出码
进程控制块 进程描述符 PCB struct task_struct;
win 打开文件:二进制 文本
Linux不区分二进制和文本
(man 1命令 2系统调用 3库函数)
库函数:
fopen fread fgets
系统调用: 实现在内核中 是用户和内核之间的桥梁
从用户态切换到内核态
open read write close linux一切皆文件
打开 读 写 关闭
系统调用执行过程:
用户空间:系统调用号 应用程序 int fd = open()
产生0*80号中断 Eax寄存器(可存四字节) 存放数据
根据系统调用号查找内核实
int fd = sys_open()
内核空间:系统调用表
操作文件的系统调用
1 int open(const char* pathname,int flags);
//用于打开一个已存在的文件
2 int open(const char* pathname,int flags,mode_t mode);
//用于新建一个文件 并设置访问权限
3 参数介绍:
pathname:将要打开的文件路径和名称
flags:打开标志 O_RDONLY 只读打开 O_WRONLY 只写打开 O_RDWR 读写打开
int fd = open()
每个进程会有自己的文件表
struct file:表示一个打开的文件(文件每打开一次产生一个)
struct inode:代表一个文件(打开多少次也只有一个)
父进程打开的文件fork()之后 子进程也可以访问 他们共享struct file节点 共享文件偏移量
C语言中:
标准输入 FILE* stdin 0
标准输出 stdout 1
标准错误输出 stderr 2
printf()->write()
每一个新进程都由fork+exec启动
#include <stdio.h>
#include <stdlib.h>
#include <unsitd.h> //open
#include <string.h>
#include <assert.h>
#include <fcntl.h> //O_RDONLY
(1)
int main()
{
int fd = open("a.txt",O_WRONLY | O_CREAT,0600); //打开文件“a.txt” O_WRONLY:以只写方式打开 O_CREAT:如果文件不存在则创建文件 0600:自身读2+写4的权限 同组人其他人无权限
assert(fd != -1);
write(fd,"hello",5); //写入“hello”占五字节
close(fd); //关闭文件
}
(2)
int main()
{
int fd = open("a.txt",O_RDONLY ); // 1 打开文件
assert(fd != -1);
char buff[128] = {0};
int n = read(fd,buff,127); //2 读取文件内容 read返回值n为实际读取到的字节数
//把文件读到末尾 read返回值为零 read() == 0
printf("buff=%s,n=%d\n",buff,n); // 3 打印文件内容和实际读取到的字节数
close(fd); // 4 关闭文件
}
(3)复制文件
思路:先打开文件1 创建新文件2 把文件1数据内容复制到文件2
int main(int argc, char* argv[])
{
if(argc != 3)
{
printf("arg err\n");
return 0;
}
char * filename = argv[1];
char * newfilename = argv[2];
//调用时使用 1 gcc -o main main.c 2 ./main a.txt b.txt
int fdr = open(filename,O_RDONLY);
int fdw = open(newfilename,O_WRONLY | O_CREAT,0600);
if ( fdr == -1 || fdw == -1)
{
printf("open file failed\n");
return 0;
}
char buff[512] = {0};
int n = 0;
while(( n = read(fdr,buff,512)) > 0)
{
write(fdw,buff,n);
}
close(fdr);
close(fdw);
}
int main(int argc,char* argv[])
{
printf("A");
write(1,"B",1);
fork();
} //BAA write直接打在屏幕上 printf先放入缓冲区程序结束调用write输出
(4)
替换进程 exec系列 通过系统调用实现
将一个已存在的进程替换成一个新的进程 id号不变
路径加名称必须写对
执行之后替换结束当前进程直接消失
int main()
{
printf("main pid=%d\n",getpid());
execl("/usr/bin/ps","ps","-f",(char*)0); //若本行执行成功 进程直接结束
printf("execl err\n"); //能执行到这里代表替换已经失败
}