搜索
查看
编辑修改
首页
UNITY
NODEJS
PYTHON
AI
GIT
PHP
GO
CEF3
JAVA
HTML
CSS
搜索
weixin_40725706
这个屌丝很懒,什么也没留下!
关注作者
热门标签
jquery
HTML
CSS
PHP
ASP
PYTHON
GO
AI
C
C++
C#
PHOTOSHOP
UNITY
iOS
android
vue
xml
爬虫
SEO
LINUX
WINDOWS
JAVA
MFC
CEF3
CAD
NODEJS
GIT
Pyppeteer
article
热门文章
1
最全的 Vue 面试题+详解答案_vue原理面试题
2
solidity语言语法总结
3
【时间序列】多变量时间序列异常检测数据集整理及标准化处理代码合集
4
HarmonyOS 鸿蒙驱动消息机制管理
5
HCIP-AI EI Developer V2.0 模拟试卷_hcia-harmonyos application developer v2.0 模拟考试
6
蔚来,还有几张底牌可打?
7
您所应了解的Python四大主流网络编程框架_esafenet python
8
【c++】获取电脑硬件信息(操作系统,CPU,内存,GPU,显卡驱动,显示设备分辨率)_c++ 获取硬件信息
9
克鲁斯卡尔算法-------最小生成树图解_克鲁斯卡尔算法求最小生成树
10
hnu云计算个人实验报告——实验七
当前位置:
article
> 正文
Unix高级编程:库函数与系统调用函数区别、文件锁、进程基础_系统调用函数 锁
作者:weixin_40725706 | 2024-03-17 13:57:55
赞
踩
系统调用函数 锁
一、库函数和系统调用之间的关系和区别(文件操作函数说明)
fopen(3)
FILE *fopen(const char *path, const char *mode);
当使用fopen(3)打开文件的时候,发生了什么?
1)首先分配了一块内存空间,用于文件内容的缓冲
2)然后调用open(2)
fputc(3)
int fputc(int c, FILE *stream);
首先将数据放入fopen(3)开辟的那块内存空间里:
1)如果内存空间不满,不会立即写入到文件,当清理缓存的时候或者或者缓存满的时候,调用"write"(2)将缓存里的内容写到文件。
2)如果内存空间满的时候,调用write(2)将缓存里的数据写入到文件,然后将fputc的内容写到缓存里。
fgetc(3)
int fgetc(FILE *stream);
调用fgetc(fp)的时候,首先到fp指向的内存空间里去找一个字符:
1)如果空间里有字符,立即返回。
2)如果没有字符,调用"read(fp->_fileno, buf, len)",buf指向了fp的内存空间。这个时候将文件的内容读取到fopen(3)开辟的那块内存空间里,这个时候再从这块内存空间里将字符读取。
fclose(3)
int fclose(FILE *fp);
首先将缓存里的数据写入到文件,然后释放缓存、调用close(2)关闭文件
"缓冲文件"
"非缓冲文件"
fflush(3)
int fflush(FILE *stream);
刷新缓冲(清理缓存),原因:感觉写入文件其实在数据在缓冲,并没有实际写入,调用fflush(3)即可。
stdin
0
标准输入
stdout
1
标准输出
stderr
2
标准错误输出
printf("hhhh"); //printf占用行缓存,没满有时不输出,加\n输出,缓冲所致
1) \n //加\n,也能输出,方法1
2) fflush(1); //加标准输出,也能输出,方法2
二、文件锁(建议锁/强制锁暂不讲)
多个进程同时访问一个文件的时候,这个文件就成为"临界资源",这个时候对这个文件的访问需要同步。
同步和异步
"同步" 事情A和事情B,只有在事情A完成之后,再进行事情B,那么AB同步。
"异步" 事情A和事情B,谁先执行都可以,执行无先后顺序,那么AB异步。
为了避免在读写同一个文件的同一个区域时发生冲突,进程之间应该遵循以下规则:
1)如果一个进程"正在写",那么"其它进程既不能写也不能读"
2)如果一个进程"正在读",那么"其它进程不能写但是可以读"
为了实现同步,在这里使用对文件加锁。"建议锁"/"强制锁",两种所都有:
"读锁" (共享锁)对一整个文件或特定区域可以加多把读锁
"写锁" (互斥锁)对一整个文件或特定区域只能加一把写锁
"fcntl"(2) //使用该系统调用函数完成对文件的加锁
#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );
功能:操作文件描述符
参数:
"fd" open(2)的返回值,指定要操作的文件(描述符)
"cmd" 命令。对文件描述符进行操作的命令
F_SETLK 设置锁-非阻塞模式,进程遇锁立即以错误返回,返回错误
F_SETLKW 设置锁-阻塞模式,进程遇锁将等待冲突锁直到锁被释放
F_GETLK 获取锁
"..." 可变参数(需要or不需要"取决与cmd参数")
"..."=="lock"
struct flock {
short l_type; /*Type of lock*/ 读锁/写锁/解锁
"F_RDLCK,F_WRLCK,F_UNLCK"
short l_whence; /*How to interpret l_start*/位置:开始/当前/末尾
"SEEK_SET, SEEK_CUR, SEEK_END"
off_t l_start; /*Starting offset for lock*/
off_t l_len; /*Number of bytes to lock*/
pid_t l_pid; /*PID of process blocking our lock
(F_GETLK only) */
};
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
/*举例验证文件锁的使用,代码参见 processA.c & processB.c*/
/* processA.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(void) {
int fd;
fd = open("aaa.txt", O_RDWR);//打开一个文件
if(fd == -1) {
perror("open");//打开失败
return 1;
}
struct flock lock; //初始化文件锁
lock.l_type = F_RDLCK;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
int ret = fcntl(fd, F_SETLK, &lock);//设置锁
if(ret == -1) {
perror("fcntl");
return 2;
}
printf("read lock success...\n");
sleep(20);
close(fd);//关闭文件
printf("read lock release...\n");
return 0;
}
/* processB.c */
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(void) {
int fd;
fd = open("aaa.txt", O_RDWR);//打开文件
if(fd == -1) {
perror("open");//打开失败
return 1;
}
struct flock lock;//初始化文件锁
lock.l_type = F_WRLCK;//读锁可直接进行/写锁需等待A完成
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
int ret = fcntl(fd, F_SETLKW, &lock);//设置锁
if(ret == -1) {
perror("fcntl");
return 2;
}
printf("read lock success...\n");
close(fd);//关闭文件
return 0;
}
此两个程序运行A的同时,在另一个标签页运行B,B可设置读锁,但B的写锁要等待A运行完毕才会执行写锁成功。
三、文件操作杂项
"chdir"(2) //cd 命令就是调用封装的 chdir 系统函数
#include <unistd.h>
int chdir(const char *path);
功能:改变工作路径
参数:"path" 目标工作路径
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"mkdir"(2) //mkdir 命令就是调用封装的 mkdir 系统函数
#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);
功能:创建一个文件夹或目录
参数:
"pathname" 要创建的文件夹名字
"mode" 新的文件夹的权限,例如 0664 或 mode & ~umask & 0777
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"getcwd"(3) //pwd 命令就是调用封装的 getcwd 系统函数
#include <unistd.h>
char *getcwd(char *buf, size_t size);
功能:获取当前的工作路径
参数:
"buf" 将当前路径的绝对路径名字拷贝到buf指定的地址空间里
"size" 拷贝的长度
返回值:
成功 - 当前工作路径的首地址指针
失败 - 返回 NULL,errno被设置
"rmdir"(2) //rm -r 命令就是调用封装的 rmdir 系统函数
#include <unistd.h>
int rmdir(const char *pathname);
功能:删除一个目录
参数:"pathname" 要删除的文件夹名字
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"link"(2) / "symlink"(2) //其中link可做命令行指令使用
#include <unistd.h>
int link(const char *oldpath, const char *newpath);
功能:为文件创建一个新名字 - 硬链接(非拷贝内容)
参数:
"oldpath" 原文件路径
"newpath" 新文件路径
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"unlink"(2)
#include <unistd.h>
int unlink(const char *pathname);
功能:删除一个硬链接文件名字
参数:"pathname" 文件名
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"rename"(2) //mv 命令就是调用封装的 rename 系统函数
#include <stdio.h>
int rename(const char *oldpath, const char *newpath);
功能:更改文件名或文件路径
参数:
"oldpath" 原文件名/路径
"newpath" 新文件名/路径
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
"chmod"(2)
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
功能:改变文件的权限
参数:
"path" 文件名
"mode" 权限属性宏
返回值:
成功 - 返回 0
失败 - 返回 -1,errno被设置
文件内容小结:
1)文件的管理(open/read/write/close/lseek/dup/dup2/fcntl/mmap...)
2)文件系统管理(stat/opendir/closedir/readdir/telldir...)
3)文件的权限、类型、软链接、硬链接、属主、属组都需弄清楚
四、进程的基本概念
进程和程序
"程序是静态的",是被存储在磁盘上,包含机器指令和数据的文件。
"进程是动态的",是被装载到内存中,被处理器操作的代码和数据。
"一个程序可被运行为多个进程"
进程快照
命令行:ps
PID TTY TIME CMD
2346 pts/0 00:00:00 bash
12376 pts/0 00:00:00 ps
PID:进程标识
TTY:控制终端次设备号
TIME:进程运行时间
CMD:进程启动命令
命令行:ps aux
VSZ:占用虚拟内存大小(KB)
RSS:占用物理内存大小(KB)
每个进程都有自己的"pid",都有自己的户口本"PCB"(进程控制器)。
PID:即Process Identification,"进程标识"。每个进程都有这么一个"非负整数形式的唯一编号"。任何时刻都是唯一的,但是"可以重用,进程被终止并被回收"以后,其PID就可以被其他进程所用。
PCB 是由操作系统的内核kernel来完成的,内核通过来管理PCB来对进程进行管理。
0 号进程:调度进程(交换进程swapper),系统内核的一部分
1 号进程:init进程,以超级用户运行的普通进程,永不终止
2 号进程:页守护进程,负责虚拟内存系统的分页操作
在linux系统中,用户进程是以一棵树来组织的。
"pstree"命令查看这棵树,格式:pstree
进程和进程之间的父子关系或者兄弟关系,亲缘关系。
"init进程"是"1号进程"
怎么去创建一个子进程?使用系统调用函数fork(2)来创建
"fork"(2)
#include <unistd.h>
pid_t fork(void);
功能:创建一个子进程
参数:void
返回值:
成功 - 在父进程里子进程的"pid被返回",在子进程里返回 0
失败 - 在父进程里返回 -1,子进程没有被创建,errno被设置
/*举例验证fork创建子进程,代码参见 fork.c*/
#include <stdio.h>
#include <unistd.h>
int main(void) {
pid_t pid;
pid = fork(); //此行开始下面就是2份代码在执行,父子进程先调用谁,由操作系统决定,人为无法判断
if(pid < 0) {
perror("fork");
return 1;
}
if(pid == 0) {
printf("I am child process...\n");
}
printf("I am father process...\n");
return 0;
}
子进程创建完成,子进程和父进程的执行是"异步"的。
子进程是父进程的不完全副本,子进程的数据区、BSS区、堆栈区(包括I/O流缓冲区),甚至参数和环境区都从父进程拷贝,"唯有代码区与父进程共享"。
调用fork函数前的代码只有父进程执行,fork函数成功返回后的代码父进程和子进程都会执行,受逻辑控制进入不同分支。
fork函数调用一次,在父进程和子进程中各返回一次,在父进程中返回所创建子进程的PID,而在子进程中返回0。
fork函数成功返回以后,父子进程各自独立运行,其被调度的先后顺序并不确定。
"getpid"(2)/"getppid"(2)
#include <sys/types.h>
#include <unistd.h>
pid_t getpid(void); //获取自己的pid
pid_t getppid(void); //获取自己父进程的pid
/*代码演示*/
printf("pid = %d\n", getpid());
printf("ppid = %d\n", getppid());
实例:
父-子(父)-子(父)-子
/*代码*/
#include <stdio.h>
#include <unistd.h>
void myfork(int c) {
pid_t pid;
if(c-- == 1) {
return ;
}
pid = fork();
if(pid == 0) {
printf("pid = %d\n", getpid());
printf("ppid = %d\n", getppid());
printf("----------------------\n");
myfork(c);
}
else
sleep(5);
return;
}
int main(void) {
int count = 4;
myfork(count);
return 0;
}
进程的退出:
"exit"(3) 和 return 的区别
return 只是完成函数的返回
exit 函数是进程的退出
在 main 函数中 return 返回之后,进程还没有结束
而调用exit函数的时候,进程就完全结束了
事实上,main函数里的return语句也会被编译器处理为类似对exit函数的调用,所以可以认为 return x 等价于 exit(x)。
"_exit"(2)
#include <unistd.h>
void _exit(int status);
功能:退出进程
参数:"status" 文件描述符
返回值:无返回值
在进程终止之前可以做一些处理工作
"atexit"(3)
#include <stdlib.h>
int atexit(void (*function)(void));
功能:向进程注册,进程终止之前调用的函数
参数:void (*function)(void) 进程结束时要调用的函数,无参数
返回值:
成功 - 返回 0
失败 - 返回非 0
/*举例验证,代码参见 atexit.c*/
#include <stdio.h>
#include <stdlib.h>
void handle(void) {
printf("oh , my god..!\n");
return;
}
int main(void) {
atexit(handle);
sleep(5);
return 0;//在return之后,在进程退出之前,printf
}
"on_exit"(3)
#include <stdlib.h>
int on_exit(void (*function)(int , void *), void *arg);
功能:向进程注册,进程终止之前调用的函数
参数:
void (*function)(int , void *) 进程结束时要调用的函数,两个参数
function函数里的 int 是 return 的数字传到int里
"arg" function函数里的第 2 个参数
返回值:
成功 - 返回 0
失败 - 返回非 0
/*举例验证,代码参见 on_exit.c*/
#include <stdio.h>
#include <stdlib.h>
void handle(int x, void *arg) {
printf("%d\t%s\n", x, (char *)arg);
return ;
}
int main(void) {
on_exit(handle, "tarena");
sleep(5);
return 2;// 或 exit(5)
}
声明:
本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:
https://www.wpsshop.cn/w/weixin_40725706/article/detail/256386
推荐阅读
article
1
NLP
学习
大纲...
一、自然语言处理概述
1
)自然语言处理:利用计算机为工具,对书面实行或者口头形式进行各种各样的处理和加工的技术,是研究人与...
赞
踩
article
JAVA
实现FTP多
文件
下载
,说一说
ftpClient
.
retrieveFileStream
方法遇到...
问题描述:在搭建好的ftp服务器上面 ,每天定时任务 从 /拍照保存目录/1/{摄像头序列号}/{日期}/{xxx.jp...
赞
踩
article
30
天学习编写
30
个
Swift
小
程序
...
更新:所有代码已经更新到
Swift
4.1,请移步github下载============================...
赞
踩
article
Windows
上
Mqtt
服务器
搭建与使用
客户端
工具
Mqtt
Box进行测试_
mqttbox
下载...
场景MQTT协议MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)...
赞
踩
article
LeetCode
两
整数
之
和
简单解
python
题解_给你
两
个
整数
a
和
b
,
不使用
运算符
+
和
...
371.
两
整数
之
和
题目:给你
两
个
整数
a
和
b ,不使用
运算符
+
和
-,计算并返回
两
整数
之
和
。示例 1:输入:a ...
赞
踩
article
wget
中文详细
使用
说明...
Wget 的
使用
wget
下载时,可以将文件重命名:复制代码 代码如下:
wget
-c "www.jbxue.com" -...
赞
踩
article
RocketMQ
集群No
route
info
of
this
topic
解决方案_
rocketmq
...
1.问题描述 在针对
RocketMQ
集群做模拟故障测试,测试环境: 1.两台linux服务器,系统配置MEM:64G...
赞
踩
article
[详细教程]新版
labelme
标注
后
的
json
文件
,
提取
不同
的
标签
后
批量
注入
到新
的
背景
中作为人工数据...
步骤一、 配置
labelme
环境二、 用
labelme
标记数据得到
json
文件
三、
提取
json
文件
出相应
标签
的
信息四、注...
赞
踩
article
LangChain
+
ChatGLM2
-
6B
搭建个人专属
知识库
_
langchain
chatgl...
之前教过大家利用
langchain
+ ChatGLM-
6B
实现个人专属
知识库
,非常简单易上手。最近,智谱 AI 研...
赞
踩
article
工具类微信
小
程序
-"你记
我
账
"-实例
源码
_
小
程序
账
单展示
源码
...
自从腾讯推出微信
小
程序
后
我
就不知不觉的有点着迷,从一开始的不完善到现在的风靡后来又推出了云开发(十足十的为开发者考虑,只...
赞
踩
article
消息队列
MQClientException
:
Send
[3]
times
,
still
fail...
原因1:未关闭防火墙防火墙未关闭,导致9876端口号未暴露出来。解决方案:systemctl stop firewall...
赞
踩
article
Java
开发
从入门到精通(七)
:
Java
的
面向对象编程
OOP
:
常用
API
...
Java
大数据
开发
和安全
开发
(一)
Java
的常用
API
1.1 Object类1.1 toString1.1 equals...
赞
踩
article
Langchain 集成
Milvus
_
langchain
milvus
...
Langchain 集成
Milvus
_
langchain
milvus
langchain
milvus
...
赞
踩
article
labelme
生成
的标注
数据
转换成
yolo
v5
格式_
labelme
yolo
...
# -*- coding: utf-8 -*-"""Time: 2021.10.26Author: Athrunsun...
赞
踩
article
12
个
“
经典
”
网站
!...
微信搜索逆锋起笔关注后回复编程pdf领取编程大佬们所推荐的 23 种编程资料!今天给你介绍
12
个
提高效率
网站
,如果你还不...
赞
踩
article
base64
在线
预览
pdf
_
base64
转
pdf
在线
...
pdf
.js下载地址 http://mozilla.github.io/
pdf
.js/建议翻墙下载,我用公司网下载不下来...
赞
踩
article
写给初学者的 HarmonyOS 教程
--
状态管理(@
State
/@
Prop
/@
Link
装饰器...
@
State
装饰的变量,或称为状态变量,一旦变量拥有了状态属性,就和自定义组件的渲染绑定起来。当状态改变时,UI 会发...
赞
踩
article
macOS
向
ntfs
格式的
移动
硬盘
写
数据
_
macos
14
ntfs
硬盘
写入...
解决
macOS
处理
ntfs
格式的
硬盘
数据
时无法修改
硬盘
内部
数据
的问题_
macos
14
ntfs
硬盘
写入
macos
14...
赞
踩
article
pytorch
中
张量
变换函数...
pytorch
中view、transpose、permute和unsqueeze函数介绍。
pytorch
中
张量
变换函数 ...
赞
踩
article
rocketmq
出现
org
.
apache
.
rocketmq
.
client
.
exception
.MQC...
本来项目好好的,突然出现
rocketmq
消息队列出现故障,查看项目日志出现以下错误:
org
.
apache
.rocketm...
赞
踩
相关标签
人工智能
数据库
数据结构与算法
java
ftp
多文件下载
swift
移动开发
ui
windows
物联网
python
leetcode
算法
操作系统
运维
RocketMQ
No route info of this topic
labelme
json
批量
数据集
图像融合
langchain
chatgpt