高级IO函数

news2024/11/17 9:32:21

1. 高级 I/O 函数

1.1 pipe

#include <unistd.h>
/*
成功返回0,失败返回-1设置error
*/
int pipe( int fd[2] );

(1)fd[0] 只能从管道读,fd[1] 只能写,默认情况下这一对文件描述符都是阻塞的(读空管道 或 写满管道 会被阻塞);

(2)写端 fd[1] 引用计数减为 0,即没有进程往管道写入数据,对 fd[0] 的 read 操作将返回 0(EOF);同理,读端 fd[0] 引用计数减为 0,对 fd[1] 的 write 操作将失败,并引发 SIGPIPE 信号;

(3)管道大小默认为 65536 字节,可以使用 fcntl 函数修改;

创建双向管道;

#include <sys/types.h>
#include <sys/socket.h>
/*
成功返回0,失败返回-1设置error
*/
int socketpair( int domain, int type, int protocol, int fd[2] );

domain 只能设置为 AF_UNIX;

1.2 dup 和 dup2

创建新的文件描述符,与 file_descriptor 指向相同的文件、管道或网络连接;

#include <unistd.h>
/*
失败返回-1设置error
*/
int dup( int file_descriptor );
int dup2( int file_descriptor_one, int file_descriptor_two );

dup返回的文件描述符总是取当前系统可用的最小整数值(一般方式是关闭标准输入或输出,其返回的就是之前关闭标准输入或输出的值),dup2返回第一个不小于 file_descriptor_two 的整数值;

注意:dupdup2 创建的新文件描述符不会继承原本文件描述符的属性;

1.3 readv 和 writev

不同内存位置上的数据,不需要拼接到一块再进行写入

#include <sys/uio.h>
/*
成功时返回读出/写入 fd 的字节数
失败返回-1设置error
*/
ssize_t readv( int fd, const struct iovec* vector, int count );
ssize_t writev( int fd, const struct iovec* vector, int count );

count 是 vector 数组的长度

1.4 sendfile

在两个文件描述符之间直接传递数据(完全在内核中操作),称为零拷贝(没有内核缓冲区和用户缓冲区之间的数据拷贝)

#include <sys/sendfile.h>
/*
成功返回传输的字节数
失败返回-1设置error
*/
ssize_t sendfile( int out_fd, int in_fd, off_t* offset, size_t count );

offset 指定从读入文件流的哪个位置开始读,如果为空,使用默认的起始位置;
count 指定在文件描述符 in_fd 和 out_fd 之间传输的字节数;

注意:in_fd 必须指向真实的文件(不能是管道和 socket),即必须支持 mmap 函数;out_fd必须是一个 socket;

1.5 mmap 和 munmap

mmap 申请一段内存空间,可作为进程间通信的共享内存,也可将文件直接映射到其中;
munmap 释放这段内存;

#include <sys/mman.h>
/*
成功返回指向目标内存的指针
失败返回 MAP_FAILED((void*)-1)并设置errno
*/
void* mmap( void *start, size_t length, int prot, int flags, int fd,
			off_t offset );
/*
成功返回 0
失败返回-1设置error
*/
int munmap( void *start, size_t length );

start 允许用户指定某个特定地址作为这段内存的起始地址,如果被设置为 NULL,系统自动分配;
length 指明需要内存的长度;
prot 设置访问权限,取值为 PROT_READ(可读)、PROT_WRITE(可写)、PROT_EXEC(可执行)、PROT_NONE(不能被访问) 这几个值的按位或;

flags 控制内存段内容被修改后程序的行为,是下表某些值的按位或(MAP_SHARED 和 MAP_PRIVATE 是互斥的);
在这里插入图片描述
fd 是被映射文件的文件描述符,一般通过 open获得;
offset 设置从文件的何处开始映射;

1.6 splice

用于在两个文件描述符之间移动数据,也是零拷贝;

#include <fcntl.h>
/*
成功返回移动字节的数量,可能返回0
失败返回 -1 并设置errno
*/
ssize_t splice( int fd_in, loff_t* off_in, int fd_out, loff_t* off_out, 
				size_t len, unsigned int flags );

(1)fd_in 是待输入数据的文件描述符;如果其为管道,off_in 必须为 NULL;否则,off_in 表示从输入数据流何处开始读数据,此时 off_in 若被设置为 NULL,表示从当前偏移位置读入;

fd_out / off_out 与之类似,用于输出数据流;

fd_in 和 fd_out 必须至少有一个是管道;

len 指定移动数据的长度

(2)flags 控制数据如何移动;被设置为下表某些值的按位或;
在这里插入图片描述
在这里插入图片描述

1.7 tee

两个管道之间复制数据,也是零拷贝操作,不消耗数据,管道上的数据仍可用于后续的读操作;

#include <fcntl.h>
/*
成功返回在两个fd之间复制的数量,可能返回0
失败返回 -1 并设置errno
*/
ssize_t tee( int fd_in, int fd_out, size_t len, unsigned int flags );

fd_in 和 fd_out 必须都是管道;flags 与 splice 相同

1.8 fcntl(file control)

#include <fcntl.h>
/*
失败返回 -1 并设置errno
*/
int fcntl( int fd, int cmd, ... );

cmd 指定执行何种类型的操作;常用操作和参数如下所示;
在这里插入图片描述
SIGIO 和 SIGURG 必须与某个文件描述符关联后才能使用,关联的方法为:使用 fcntl 为文件描述符指定宿主进程或进程组。宿主进程或进程组将捕获这两个信号;
被关联的文件描述符可读或可写时,系统触发 SIGIO 信号;其上有带外数据可读时,触发 SIGURG 信号;
使用 SIGIO 时,还需要利用 fcntl设置其 O_ASYNC 标志;
在这里插入图片描述

2. Linux 服务器程序规范

2.1 日志

2.1.1 Linux 系统日志

(1)Linux 提供一个守护进程来处理系统日志 —— rsyslogd;

其能接收用户日志和内核日志;

用户进程调用 syslog生成系统日志,将日志输出到 /dev/log 中(AF_UNIX 类型),rsyslogd 监听该文件获得用户进程输出;

内核日志由 printk等打印到内核的环状缓冲(ring buffer)中,该缓冲直接映射到 /proc/kmsg 文件中,rsyslogd 读取该文件获得内核日志;

(2)输出,默认情况下,调试信息会保持到 /var/log/debug 中,普通信息到 /var/log/messages,内核消息到 /var/log/kern.log;

rsyslogd 的主配置文件是 /etc/rsyslog.conf,可以配置内核日志输入路径、包含哪些子配置文件等;

2.1.1 syslog 函数

(1)

#include <syslog.h>
void syslog( int priority, const char* message, ... );

priority 是设施值(默认为 LOG_USER)和日志级别的按位或;
日志级别如下所示:

#define LOG_EMEGE		0	/* 系统不可用 */
#define LOG_ALERT		1	/* 报警,需要立即采取动作 */
#define LOG_CRIT		2	/*非常严重情况 */
#define LOG_ERR			3	/* 错误 */
#define LOG_WARNING		4	/* 警告 */
#define LOG_NOTICE		5	/* 通知 */		
#define LOG_INFO		6	/* 信息 */
#define LOG_DEBUG		7	/* 调试 */

(2)改变 syslog 的默认输出方式,进一步结构化日志内容

void openlog( const char* ident, int logopt, int facility );

ident 指定的字符串将被添加到日志消息的日期和时间之后,通常被设定为程序的名字;
logopt 对后续的 syslog 调用的行为进行配置,可取下列值的按位或:

#define LOG_PID			0x01	/* 日志信息中包含程序PID */
#define LOG_CONS		0x02	/* 如果消息不能记录到日志文件,则打印到终端 */
#define LOG_ODELAY		0x04	/* 延迟打开日志功能直到第一次调用 syslog  */
#define LOG_NDELAY		0x08	/* 不延迟打开日志功能 */

facility 可用来修改 syslog 中的默认设施值;

(3)设置 syslog 日志掩码,日志级别大于日志掩码的日志信息被系统忽略;

/* 返回先前的日志掩码值 */
int setlogmask( int maskpri );

(4)关闭日志功能

void closelog();

2.2 用户信息

2.2.1 UID、EUID、GID 和 EGID
#include <sys/types.h>
#include <unistd.h>
uid_t getuid();				/* 获取真实用户ID */
uid_t geteuid();			/* 获取有效用户ID */
gid_t getgid();				/* 获取真实组ID */
gid_t getegid();			/* 获取有效组ID */
int setuid( uid_t uid );
int seteuid( uid_t uid );
int setgid( gid_t gid );
int setegid( gid_t gid );

一个进程拥有两个用户 ID:UID 和 EUID;EUID 存在的目的是方便资源访问:使得运行程序的用户拥有该程序的有效用户的权限,比如 su;

文件如果由 set-user-id(s) 标志,运行该文件时,其有效用户就是该程序的所有者;

root 的 UID 为 0;有效用户为 root 的进程称为特权进程;

2.2.2 切换用户

从 root 身份启动进程切换到普通用户身份运行,调用 setgidsetgid 实现;

2.3 进程间关系

2.3.1 进程组

每个进程都隶属于一个进程组,除了 PID 外,还有 PGID;

#include <unistd.h>
/*
成功返回进程 PID 所属进程组的 PGID
失败返回-1并设置errno
*/
pid_t getpgid( pid_t pid );
/*
成功返回 0
失败返回-1并设置errno
*/
int setpgid( pid_t pid, pid_t pgid );

(1)每个进程组都有一个首领进程,其 PID 和 PGID 相同;进程组将一直存在,直到其中所有进程都退出或加入其他进程组;

(2)setpgid 中 pid 为 0,表示设置当前进程的 PGID 为 pgid;如果 pgid 为 0,则使用 pid 作为 PGID;

(3)一个进程只能设置自己或其子进程的 PGID,当子进程调用 exec系列函数后,不能在父进程对它设置 PGID;

2.3.2 会话

有关联的进程组将形成一个会话,下面函数用于创建一个会话;

#include <unistd.h>
/*
成功返回新的进程组的 PGID
失败返回-1并设置errno
*/
pid_t setsid( void );
pid_t getsid( pid_t pid );

不能由进程组的首领进程创建会话,会产生错误;对非首领进程,调用 setsid,会使得调用进程成为会话的首领,会新建一个进程组,调用进程成为该组首领,调用进程将甩开终端;

会话ID:会话首领所在的进程组的 PGID;

2.4 改变工作目录和根目录

#include <unistd.h>
/*获取和改变进程工作目录*/
char* getcwd( char* buf, size_t size );
int chdir( const char* path );
/*改变进程根目录*/
int chroot( const char* path );

(1)buf 指向的内存用于存储进程当前工作目录的绝对路径,其大小由 size 指定;

如果当前工作目录的绝对路径长度(加上最后一个’\0’)大于 size,返回 NULL,并设置 errno 为 ERANGE;

(2)chdirchroot 成功返回 0,失败返回 -1 并设置 error;

chroot不改变进程当前的工作目录,调用其之后,仍需要使用 chdir(”/“)来将工作目录切换至新的根目录,只有特权进程才能改变根目录;

2.5 进程后台化

#include <unistd.h>
/*成功返回 0, 失败返回-1并设置errno*/
int daemon( int nochdir, int noclose );

nochdir 为 0,工作目录被设置为 “/”,否则为当前工作目录;
noclose 为 0 时,标准输入、输出、错误输出都被重定向到 /dev/null 文件,否则,继续用原先设备;

参考

《Linux 高性能服务器》

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1295326.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

甘草书店:#10 2023年11月24日 星期五 「麦田创业分享2—世界奇奇怪怪,请保持可可爱爱」

今日继续分享麦田创业经验。 如果你问我&#xff0c;创业过程中是否想过放弃。那么答案是&#xff0c;有那么一次。 那时想要放弃的原因并不是辛苦没有回报&#xff0c;或是资金短缺&#xff0c;而是没能理解“异见者”。 其实事情非常简单&#xff0c;现在反观那时的自己&a…

AUTOSAR CP Port Driver简介

Port Driver 1 背景2 基于 EB 及 TC39X 配置3 Port API 使用1 背景 Port driver 在 AUTOSAR 中是一个比较冷门的模块,基本上在 MCAL 层级,关注的人也少,他由不像其他模块那样通用型比较强,Port 在每种内核的 MCU 的配置都有区别,甚至有些芯片直接没有 Port 模块,使用其他方…

Java多线程并发(二)

四种线程池 Java 里面线程池的顶级接口是 Executor&#xff0c;但是严格意义上讲 Executor 并不是一个线程池&#xff0c;而只是一个执行线程的工具。真正的线程池接口是 ExecutorService。 newCachedThreadPool 创建一个可根据需要创建新线程的线程池&#xff0c;但是在以前…

RFID在新能源工厂大放异彩

RFID在新能源工厂大放异彩 我国在十四五规划中提出了建设绿色低碳发展的目标&#xff0c;新能源产业成为了国家发展的重点领域之一&#xff0c;开始大力支持各种新能源厂商发展。各个厂商之间不仅比产品、比技术。也比生产想要降本增效&#xff0c;为了实现这一目标&#xff0…

多功能智能遥测终端机 5G/4G+北斗多信道 视频采集传输

计讯物联多功能智能遥测终端机&#xff0c;全网通5G/4G无线通信、弱信号地区北斗通信&#xff0c;多信道自动切换保障通信联通&#xff0c;丰富网络接口及行业应用接口&#xff0c;支持水利、环保、工业传感器、控制终端、智能终端接入&#xff0c;模拟量/数字量/信号量采集&am…

Mysql 日期函数大全

一、时间函数 &#xff08;一&#xff09;、获取当前时间 1、NOW() 获取当前日期和时间&#xff0c;在程序一开始执行便拿到时间 返回格式 YYYY-MM-DD hh:mm:ss eg&#xff1a; NOW() 得到 2023-12-03 12:20:02 NOW(),SLEEP(2),NOW() 得到 2023-12-03 12:20:02 | 0 | 2023-…

网安领域含金量最高的证书有哪些?看这1篇就足够了!

文章目录 一、前言二、CISP三、CISAW四、NISP五、为什么很多人考不下来 一、前言 现在想找网络安全之类的工作&#xff0c;光有技术是不够的&#xff0c;还得有东西证明自己&#xff0c;网安三大敲门砖&#xff1a;CTF、漏洞证明和专业证书。 对于CTF的话只是少数人能参加的&…

某度旋转验证码v2 逆向分析

v2主要依据是核心 JS 文件mkd_v2.js 版本&#xff0c;如下图所示&#xff1a; 第一次 https://passport.baidu.com/cap/init 接口&#xff0c;请求的 ak 是固定值&#xff0c;当然不同场景不同网站是不一样的&#xff0c;_ 时间戳&#xff0c;ver1&#xff0c;返回值 as、tk 都…

制作一个RISC-V的操作系统四-嵌入式开发介绍

文章目录 什么是嵌入式开发交叉编译查看一些GCC文件夹 调试器GDB相关语法命令 模拟器QEMUQEMU的安装和使用项目构造工具MakeMakeFile的构成make的运行 练习4-1练习4-2练习4-3 什么是嵌入式开发 程序跑到开发板上&#xff0c;或者说运行到硬件上 交叉编译 简单理解交叉编译来说…

12.8作业

1. 使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是…

SQL Server——权限管理

一。SQL Server的安全机制 SQL Server 的安全性是建立在认证和访问许可两种安全机制之上的。其中&#xff0e;认证用来确定登录Sal Server 的用户的登录账户和密码是否正确&#xff0e;以此来验证其是否具有连接SQL Server 的权限;访问许可用来授予用户或组能够在数据库中执行哪…

这些接口自动化测试工具如果不知道,就真out了!

一、Postman Postman是一款广受欢迎的API测试工具&#xff0c;除了手动发送HTTP请求的基本功能&#xff0c;它还提供了自动化测试和脚本测试的功能&#xff0c;非常适合进行HTTP接口的自动化测试。 二、Rest-Assured Rest-Assured是一个Java库&#xff0c;专为REST服务的测试…

H5ke14--1--拖放

介绍drag,drop 一.被拖动元素,目标(释放区) 元素要设置dragable属性:true,false,auto 被拖动元素上面有三个事件,drag,dragend,按下左键,移动种,鼠标松,这三个事件一般只用获取我们的被拖动元素 冒泡:event是可以继承的,mouseevent鼠标事件,dragevent拖放事件,前面都是一个…

可视化监控/安防视频云平台公共区域人员行为安全监控方案

大家在浏览新闻时&#xff0c;经常会看到某某地区有人员摔倒&#xff0c;长时间无人发现或人员闯入某危险区域管理人员未及时劝离&#xff0c;导致发生了意外事故的新闻。由于人力资源和人为巡检能力有限&#xff0c;在很多公共区域无法及时检测人员行为从而导致危险发生。为确…

Spring Boot实现接口幂等

Spring Boot实现接口幂等 1、pom依赖 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http:…

MagicAnimate

简介 新加坡国立大学 Show 实验室和字节联合做了一项类似的研究。他们提出了一个基于扩散的框架 MagicAnimate&#xff0c;旨在增强时间一致性、忠实地保留参考图像并提升动画保真度。并且&#xff0c;MagicAnimate 项目是开源的&#xff0c;目前推理代码和 gradio 在线 demo …

Java 简易版 TCP(一对一)聊天

客户端 import java.io.*; import java.net.Socket; import java.util.Date; import javax.swing.*;public class MyClient {private JFrame jf;private JButton jBsend;private JTextArea jTAcontent;private JTextField jText;private JLabel JLcontent;private Date data;p…

Esxi7Esxi8设置VMFSL虚拟闪存的大小

Esxi7Esxi8设置VMFSL虚拟闪存的大小 ESXi7,8 默认安装会分配一个 VMFSL(VMFS-L)(Local VMFS)很大空间(120G), 感觉很浪费, 实际给 8G 就可以了, 最少 6G , 经实验,给2G没法安装 . Esxi7是虚拟闪存的 修改的方法是: 在安装时修改 设置 autoPartitionOSDataSize8192 在cdromBoo…

C语言WFC实现绘制Lagrange插值多项式曲线的函数

前言&#xff08;引用&#xff09;&#xff1a; 拉格朗日多项式插值 插值方法有许多&#xff0c;常用的、基本的有&#xff1a;拉格朗日多项式插值、牛顿插值、分段线插值、Hermite插值和三次样条插值。这里只将一下拉格朗日多项式插值法&#xff1a; 方法应用 通缩点说&…

Private Set Intersection from Pseudorandom CorrelationGenerators 最快PSI!导览解读

目录 一、概述 二、相关介绍 三、性能对比 四、技术细节 1.KKRT 2.Pseudorandom Correlation Generators 3.A New sVOLE-Based BaRK-OPRF 4.BaRK-OPRF 五、总结 参考文献 一、概述 这篇文章的主要脉络和核心思想是探讨如何利用伪随机相关生成器&#xff08;PCG&#…