open()\fork()和flock()

1.open()函数

#include <sys/file.h>

(1)函数名:

open

(2)头文件:

<io.h>

(3)函数原型:
int open(char *pathname,int oflag,[,int auth]);
(4)参数:

(1)pathname:待打开/创建文件的路径名(如 C:/cpp/a.cpp);

(2)oflag:是打开/创建文件的模式,这个参数可由以下常量(定义于 fcntl.h)通过逻辑或构成.

(3)auth:仅当创建新文件时(即 使用了O_CREAT 时)才使用,用于指定文件的访问权限位(access permission bits).

(5)注解:

oflag 用于指定文件的打开/创建模式,这个参数可由以下常量(定义于 fcntl.h)通过逻辑或构成

打开/创建文件时,至少得使用以下三个常量中的一个

O_RDONLY 只读模式

O_WRONLY 只写模式

O_RDWR 读写模式

以下常量是选用的:

O_APPEND 每次写操作都写入文件的末尾

O_CREAT 如果指定文件不存在,则创建这个文件

O_EXCL 如果要创建的文件已存在,则返回 -1,并且修改 errno 的值

O_TRUNC 如果文件存在,并且以只写/读写方式打开,则清空文件全部内容(即将其长度截短为0)

O_NOCTTY 如果路径名指向终端设备,不要把这个设备用作控制终端

O_NONBLOCK 如果路径名指向 FIFO/块文件/字符文件,则把文件的打开和后继 I/O


 

#include <stdio.h>

#include<io.h>

#include<fcntl.h>

int main()

{

int fd;

char buf[100];

fd=open("test.txt",O_RDWR);

if(fd==-1)

{

printf("open error\n");

return -1;

}

read(fd,buf,100);

printf("%s\n",buf);

close(fd);

return 0;

}

2.flock() 函数

进程之间的通信以及资源共享,多进程之间文件共享冲突

exp:

写进程-------->数据文件--------->读进程

多进程读写文件冲突

与常规的多进程读写冲突是有区别的:

传统的多进程是统一服务中通过fork派生出来的多进程,读写冲突通常是对内存中的数据结构进行读写。

该数据文件更新场景下的多进程,产生冲突的操作对象是文件,而且这里的进程可能是独立的无任何关系的进程。

文件🔓flock

flock -apply or remove an advisory lock on an open file

(1)advisory lock

(2)open file

共享锁与互斥锁

linux中flock系统调用的原型:


 

#include <sys/file.h>

int flock (int fd ,int operation);

当flock执行成功,返回0,当出现错误,返回-1,并设置相应的errno

operation:使用LOCK_SH 或者LOCK_EX常量,分别对应共享锁和排他锁。

LOCK_SH:共享锁,允许多个进程同时访问文件,但只有一个进程可以修改文件。(读锁)

LOCK_EX:排他锁,允许一个进程修改文件,但其他进程不能访问。(写锁)

LOCK_NB:非阻塞锁,如果文件已经被锁定,则立即返回。

LOCK_UN:解锁,释放文件锁。

 

3.fork()函数

用于创建一个进程,所创建的进程赋值父进程的代码段/数据段/BSS段/堆栈/等所有的用户空间信息,在内核中操作系统重新为其申请了一个PCB,并使用父进程的PCB进行初始化

(1)fork()函数的原型

pid_t fork(void);//pid_t为int类型进行了重载

pid_t getpid();//获取当前进程的进程号

pid_t getppid();//获取当前进程的父进程的pid
 

/*

* 主函数

* 无参数

* 返回值:程序执行结果,0表示成功,非0表示失败

*/

int main()

{

pid_t fpid; // 存储fork函数返回值的变量

int count = 0; // 用于计数的变量

// 创建一个新的进程

fpid = fork();

// 判断fork函数调用是否成功

if(fpid < 0)

{

printf("fork error\n"); // fork函数调用失败,打印错误信息

return -1; // 返回错误码

}

else if (fpid == 0)

{

// 这里是子进程的代码段

printf("child process pid = %d, ppid = %d\n", getpid(), getppid()); // 打印子进程的PID和父进程的PID

printf("子进程\n");

count++; // 子进程计数加一

}

else

{

// 这里是父进程的代码段

printf("parent process pid = %d, ppid = %d\n", getpid(), getppid()); // 打印父进程的PID和父进程的父进程的PID

printf("父进程\n");

count++; // 父进程计数加一

}

// 打印计数结果

printf("统计结果是:%d\n",count);

return 0; // 程序执行成功,返回0

}
(2)fork()函数的特性

它仅仅被调用一次,却能够返回两次,有三种不同的返回值:

1.在父进程中,fork返回新创建子进程的进程ID

2.在子进程中,fork返回0

3.如果出现错误,fork返回-1

exp:

A进程父进程 B进程是子进程


A进程

pid = fork();

pid == "子进程的进程ID"


B进程

pid = fork();

pid == 0;

因此我们可以通过fork返回的值来判断当前进程是子进程还是父进程。

(注: fork 调用生成的新进程与其父进程谁先执行不一定,哪个进程先执行要看系统的进程调度策略)

fpid的值(fork()的值)为何在父子进程中不同

相当于链表:进程形成了链表,父进程的fpid(p相当于point)指向子进程。子进程没得指。

(3)fork()函数的执行过程

(1)申请pid

(2)申请PCB结构

(3)复制父进程的PCB

(4)将子进程的运行状态设置为不可执行的

(5)将子进程的某些属性清零,某些保留,某些修改

(6)复制父进程的页

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值