135 Linux 系统编程12,linux命令重定向,dup 和dup2,fcntl实现dup和dup2 ,进程和程序概念,虚拟内存和物理内存映射关系,pcb进程块详解

一 linux 命令中重定向,使用>实现

通过 大于号  将前面的内容写入到某一个地方

cat main.c > b.txt   //cat main 本身的意思是 显示main.c的值,后面加上 > b.txt 会将显示在屏幕上的字符全部写到b.txt中

例子:将 ls -l 的内容 通过重定向 保存到 list.txt中

hunandede@hunandede-virtual-machine:~$ ls -l > list.txt
hunandede@hunandede-virtual-machine:~$ cat list.txt 
total 80
drwxrwxr-x  2 hunandede hunandede 4096 2月  20 18:55 aaa
drwxrwxr-x  4 hunandede hunandede 4096 2月  21 15:16 day02
drwxrwxr-x 11 hunandede hunandede 4096 2月  23 17:47 day03
drwxrwxr-x  2 hunandede hunandede 4096 2月  28 08:19 day04
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Desktop
drwxr-xr-x  3 hunandede hunandede 4096 1月  23 23:28 Documents
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Downloads
-rw-r--r--  1 hunandede hunandede 8980 1月  23 20:24 examples.desktop
drwxrwxr-x  2 hunandede hunandede 4096 2月  20 17:39 head
-rw-rw-r--  1 hunandede hunandede    0 2月  28 08:23 list.txt
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Music
drwxrwxr-x  2 hunandede hunandede 4096 1月  23 23:47 mydocument
drwxrwxr-x  3 hunandede hunandede 4096 2月  19 14:05 nginx
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Pictures
drwxrwxr-x  3 hunandede hunandede 4096 2月  23 00:40 projects
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Public
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Templates
drwxr-xr-x  2 hunandede hunandede 4096 1月  23 21:50 Videos
drwxr-xr-x  3 hunandede hunandede 4096 1月  23 21:04 下载

二 dup 和dup2 函数 重点是dup2函数的理解和应用

重定向对象的函数就是 dup 和dup2

dup 函数 非重点

函数原型

       #include <unistd.h>

       int dup(int oldfd);
       
 

函数意思

The  dup()  system  call  creates  a copy of the file descriptor oldfd,

dup函数主要是将 参数fd 拷贝一份,有就是让 多个fd 指向同一个文件

返回值:

成功,返回可以使用的新的值

失败,返回-1,errno被设置

RETURN VALUE
       On success, these system calls return the new descriptor.  On error, -1
       is returned, and errno is set appropriately.
 

dup2 函数 重点

函数原型

       #include <unistd.h>

int dup2(int oldfd, int newfd);

函数参数

oldfd 

newfd

函数意义:

使用oldfd 的值 替换 newfd的值

也就是说newfd也会指向oldfd的内容

返回值

成功的话,返回newfd 的值,失败返回-1,errno 被设置。

例子验证:

dup例子

//dup例子int main(int argc , char * argv[]) {int  ret = 0;//int fd = open(argv[1], O_RDWR);int fd = open("/home/hunandede/projects/linuxcpp/main.cpp", O_RDWR);//int fd = open("/home/hunandede/projects/linuxcpp/dict.txt", O_RDWR);if(fd == -1){perror("open file fail \n");ret = fd;return ret;}int fd2 = dup(fd);if (fd2==-1) {perror("dup fd error");ret = fd2;return ret;}printf("fd = %d,fd2 = %d\n",fd,fd2);//那么这里可以通过fd2读取fd中的数据吗?测试一下//测试中,我们发现,第一个bufread 前三个字符是 -17 -69 -65, 这是UTF-8格式的前三位,char bufread[10] = { 0 };ret = read(fd2,bufread,10);if (ret<0) {perror("read fd2 error\n");return ret;}else {cout << bufread << endl;}bufread[10] = { 0 };ret = read(fd2, bufread, 10);if (ret < 0) {perror("read fd2 error\n");return ret;}else {cout << bufread << endl;}//前面使用fd2都是可以读取到的,且第二次读取会紧挨着第一次读取到的位置//那么我们接着从fd读,是否可以呢?结果是可以的,那么我们要close 的时候,要close几次呢?bufread[10] = { 0 };ret = read(fd, bufread, 10);if (ret < 0) {perror("read fd error\n");return ret;}else {cout << bufread << endl;}ret= close(fd);cout << "start close rer " << ret<<  endl;ret = close(fd2);cout << "end close ret " << ret <<endl;return 0;
}

dup2例子

//dup2例子,注意两个问题:
//1.open几个file,就要close几个file
//2.如果使用不同的fd,对同一个文件,进行读写,那么读取的位置不会发生变化,每次都在上一次读取的位置停留int main() {int ret = 0;int fd = open("/home/hunandede/projects/linuxcpp/main.cpp", O_RDWR);int fd2 = open("/home/hunandede/projects/linuxcpp/dict.txt", O_RDWR);cout << fd << "  " << fd2 << endl;ret = dup2(fd,fd2);//fd中的内容替换了fd2中的内容,fd还是3,fd2还是4,不过是fd2指向的已经变成fd的指向了cout << "after " << fd << "  " << fd2 << endl;char readbuf[10] = { 0 };read(fd2,readbuf,10);cout << readbuf << endl;readbuf[10] = { 0 };read(fd2, readbuf, 10);cout << readbuf << endl;readbuf[10] = { 0 };read(fd, readbuf, 10);cout << readbuf << endl;ret = close(fd);cout << "ret = " << ret << endl;ret = close(fd2);cout << "retaaa = " << ret << endl;return 0;
}

三 fcntl实现dup 和 dup2 知道就行

//fcntl实现dup, 知道有这种写法就行
int main() {cout << "start " << endl;int fd = open("/home/hunandede/projects/linuxcpp/main.cpp", O_RDWR);int fd2 = fcntl(fd,F_DUPFD,0);
cout << fd << "  " << fd2 << endl;    //最后一个参数,表示我们想要的fd的值,但是结果为 3 和 4,这是因为0,已经被占用,系统默认给一个可以使用的空闲的fd。int fd3 = fcntl(fd,F_DUPFD,7);//结果为7 这是因为7没有被使用char readbuf[10] = { 0 };read(fd2, readbuf, 10);cout << readbuf << endl;readbuf[10] = { 0 };read(fd2, readbuf, 10);cout << readbuf << endl;readbuf[10] = { 0 };read(fd, readbuf, 10);cout << readbuf << endl;int ret = close(fd);cout << "ret = " << ret << endl;ret = close(fd2);//clost 这个也不会error,成功关闭。cout << "retaaa = " << ret << endl;return 0;
}

四,进程和程序,

程序和进程

程序,是指编译好的二进制文件,在磁盘上存放

           不占用系统资源(cpu、内存、打开的文件、设备、锁....)

进程,是一个抽象的概念,与操作系统原理联系紧密。进程是活跃的程序,占用系统资源。在内存中执行。(程序运行起来,产生一个进程)

程序 → 剧本(纸) 进程 → 戏(舞台、演员、灯光、道具...)

同一个剧本可以在多个舞台同时上演。同样,同一个程序也可以加载为不同的进程(彼此之间互不影响)

如:同时开两个终端。各自都有一个bash但彼此ID不同。

五 多道程序设计: 了解

我们会一边看小说,一边听歌,这说明计算机 在 同时的进行两个不同的进程,一个QQ小说,一个千千静听

那么计算机是怎么做到的呢?

在单核CPU 的年代,是通过

它们在管理程序控制之下,相互穿插的运行。多道程序设计必须有硬件基础作为保证。

时钟中断即为多道程序设计模型的理论基础。 并发时,任意进程在执行期间都不希望放弃cpu。因此系统需要一种强制让进程让出cpu资源的手段。时钟中断有硬件基础作为保障,对进程而言不可抗拒。 操作系统中的中断处理函数,来负责调度程序执行。

在多道程序设计模型中,多个进程轮流使用CPU (分时复用CPU资源)。而当下常见CPU为纳秒级,1秒可以执行大约10亿条指令。由于人眼的反应速度是毫秒级,所以看似同时在运行。

1s = 1000ms, 1ms = 1000us, 1us = 1000ns    1000000000

实质上,并发是宏观并行,微观串行!

六 虚拟内存和物理内存映射关系

cpu执行代码的大致逻辑如下

我们在这里是要知道这个 MMU,MMU存在于CPU 的内部,是一个计算机的硬件,

主要功能是:

虚拟地址到物理地址的转换(即虚拟内存管理)、 我们在这里,主要了解这个功能

内存保护、也就是 修改 内存 访问级别。我们在这里,还需要了解这个功能

中央处理器高速缓存的控制  我们在这里,暂时不需要了解这个功能

关于 虚拟内存地址到 物理内存地址的转换

那么这个物理内存和虚拟内存分别指的是什么?他们又是怎么映射的呢?

当每一个程序跑起来的时候,就会给这个程序一个虚拟的内存,如下图左边的部分,

物理内存就是我们买电脑时配置的那块内存,当前假设是512M的金士顿的内存条

物理内存和虚拟内存通过MMU 这个中间翻译官进行映射

好,我们把上图再完善一下,当同时有两个进程 a.out  和 b.out 跑起来的情况

最终图:

也就是,因为不同的进程的kernel中的元素 通过 MMU 最后 映射的物理内存是在 同一片 区域的,因此才有后面学习的进程间通讯的内容,不然怎么通讯呢?

关于 内存保护、也就是 修改 内存 访问级别

从前面的图我们了解到,如果是从user 区域的数据,通过MMU 映射到物理内存

如果是从kernel区域的数据,通过MMU也是映射到物理内存。

那么映射的这个物理内存是怎么区分的呢?

实际上 是MMU做了事情,如果MMU发现你的变量是从user 区域过来的,则在映射成物理内存的时候,会给这个物理内存映射成3级

如果MMU发现你的变量是从kernel 区域过来的,则在映射成物理内存的时候,会给这个物理内存映射成0级

当我们使用write 函数要从user 写到kernel的时候,MMU会将这个3级转化成0级,慢就慢在这里。慢在转化的这个过程。

七 pcb进程块详解
 

我们知道,每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。

/usr/src/linux-headers-3.16.0-30/include/linux/sched.h文件中可以查看struct task_struct 结构体定义。其内部成员有很多,我们重点掌握以下部分即可:

* 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。

* 进程的状态,有 初始态 就绪、运行、挂起、停止等状态。

* 进程切换时需要保存和恢复的一些CPU寄存器。

* 描述虚拟地址空间的信息。

* 描述控制终端的信息。

* 当前工作目录(Current Working Directory)。

* umask掩码。

* 文件描述符表,包含很多指向file结构体的指针。

* 和信号相关的信息。

* 用户id和组id

* 会话(Session)和进程组。

* 进程可以使用的资源上限(Resource Limit)。

八 linux 相关的环境变量

8.1 使用 env命令查看所有的环境变量

常用的环境变量

LD_LIBRARY_PATH: 动态连接器

PATH: 记录可执行文件目录位置的

SHELL: 记录当前使用的解释器是那个

TERM:当前终端类型是啥,也就是那个黑框框类型是啥,在图形界面终端下它的值是xterm,终端类型决定了一些程序的输出显示方式。比如图形界面终端可以显示汉字,而字符终端一般不行。

LANG 语言和local,决定了字符编码以及时间,货币等信息的显示形式

HOME 当前用户主目录的路径,很多程序需要在主目录下保存配置文件,使得每个用户在运行该程序时都有自己的一套配置。

8.2 使用 echo $xxx 查看某一个具体的环境变量

echo 是回显的意思,如下的语句是显示PATH环境变量的值

echo $PATH

8.3 代码获取 环境变量,getenv函数

获取环境变量值

    char *getenv(const char *name); 成功:返回环境变量的值;失败:NULL (name不存在)

练习:编程实现getenv函数。  【getenv.c】

8.4 设置 环境变量 ,setenv函数

设置环境变量的值

    int setenv(const char *name, const char *value, int overwrite);   成功:0;失败:-1

参数overwrite取值: 1:覆盖原环境变量

0:不覆盖。(该参数常用于设置新环境变量,如:ABC = haha-day-night)

8.5 删除环境变量的定义, unsetenv函数

    int unsetenv(const char *name); 成功:0;失败:-1

注意事项:name不存在仍返回0(成功),当name命名为"ABC="时则会出错。

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

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

相关文章

JavaScript最新实现城市级联操作,json格式的数据

前置知识&#xff1a; <button onclick"doSelect()">操作下拉列表</button><hr>学历&#xff1a;<select id"degree"><option value"0">--请选择学历--</option><option value"1">专科<…

配置前端项目到 github-pages

Quickstart for GitHub Pages - GitHub Docs

【Day59】代码随想录之动态规划_647回文子串_516最长回文子序列

文章目录 动态规划理论基础动规五部曲&#xff1a;出现结果不正确&#xff1a; 1. 647回文子串2. 516最长回文子序列 动态规划理论基础 动规五部曲&#xff1a; 确定dp数组 下标及dp[i] 的含义。递推公式&#xff1a;比如斐波那契数列 dp[i] dp[i-1] dp[i-2]。初始化dp数组…

AxureCloud配置文件详细介绍

AxureCloud配置文件详细介绍 原文地址&#xff1a;https://docs.axure.com/axure-cloud/business/custom-settings-json/ 通过修改 customsettings.json 可以修改AxureCloud私有部署的域名、端口、HTTPS、存储目录、是否开启插件等, 默认安装的路径为: C:\Program Files\Axure…

白介素IL-17靶点作用机制、全球在研管线与临床试验结果汇总分析

IL-17与化脓性汗腺炎疾病 化脓性汗腺炎&#xff08;Hidradenitis suppurativa&#xff0c;HS&#xff09;&#xff0c;也称为反痤疮&#xff0c;是一种慢性致残性和衰弱性炎症性疾病&#xff0c;其特征是深部疼痛的结节和脓肿、瘘管、窦道和疤痕&#xff0c;全球发病率约为1%~…

Mysql的储存引擎

储存引擎介绍 1. 文件系统 操作系统存取数据的一种机制 2. 文件系统类型 不管使用什么文件系统&#xff0c;数据内容不会变化 不同的是&#xff0c;存储空间、大小、速度 3. MySQL存储引擎 可以理解为&#xff0c;MySQL的“文件系统”&#xff0c;只不过功能更加强大 4. MySQL…

安装极狐GitLab Runner并测试使用

本文继【新版极狐安装配置详细版】之后继续 1. 添加官方极狐GitLab 仓库&#xff1a; 对于 RHEL/CentOS/Fedora&#xff1a; curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash2. 安装最新版本的极狐G…

Django项目使用vue打包前端页面使用教程

一、vue打包&#xff1a; 一般使用 npm run build 进行打包&#xff0c;打包完成后会生成一个dist文件夹 二、修改vue.config.js配置 vue.config..js配置里面增加&#xff1a; assetsDir: static 三、修改Django项目 将Django的static文件夹删除&#xff0c;移动di…

Flink动态分区裁剪

1 原理 1.1 静态分区裁剪与动态分区裁剪 静态分区裁剪的原理跟谓词下推是一致的&#xff0c;只是适用的是分区表&#xff0c;通过将where条件中的分区条件下推到数据源达到减少分区扫描的目的   动态分区裁剪应用于Join场景&#xff0c;这种场景下&#xff0c;分区条件在joi…

Oracle中序列

1. Sequence 定义 在Oracle中可以用SEQUENCE生成自增字段。Sequence序列是Oracle中用于生成数字序列的对象&#xff0c;可以创建一个唯一的数字作为主键。 2. 为什么要用 Sequence 你可能有疑问为什么要使用序列&#xff1f; 不能使用一个存储主键的表并每次递增吗&#xf…

milvus upsert流程源码分析

milvus版本:v2.3.2 整体架构: Upsert 的数据流向: 1.客户端sdk发出Upsert API请求。 import numpy as np from pymilvus import (connections,Collection, )num_entities, dim 4, 3print("start connecting to Milvus") connections.connect("default",…

11.题目:编号3272 小蓝的漆房

题目&#xff1a; ###本题主要考察暴力&#xff0c;枚举&#xff0c;模拟 #include<bits/stdc.h> using namespace std; const int N1e410; int a[N],b[N]; int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int num;cin>>num;//样例个数循环for(int i…

socket套接字

前言 两个应用程序如果需要进行通讯最基本的一个前提就是能够唯一的标示一个进程&#xff0c;我们知道IP层的ip地址可以唯一标示主机&#xff0c;而TCP层协议和端口号可以唯一标示主机的一个进程&#xff0c;这样我们可以利用ip地址&#xff0b;协议&#xff0b;端口号唯一标示…

许战海矩阵|佐香园:“熟酱”的爆品战略

佐香园是辽宁帝华味精食品有限公司的主导品牌&#xff0c;是一个拥有自主研发与生产经营能力的民营企业&#xff0c;主要生产和销售香料、调味料以及食品添加剂等产品。该品牌自创办以来&#xff0c;一直坚持以市场为导向&#xff0c;走专业化发展之路&#xff0c;打造全方位的…

LACP——链路聚合控制协议

LACP——链路聚合控制协议 什么是LACP&#xff1f; LACP&#xff08;Link Aggregation Control Protocol&#xff0c;链路聚合控制协议&#xff09;是一种基于IEEE802.3ad标准的实现链路动态聚合与解聚合的协议&#xff0c;它是链路聚合中常用的一种协议。 链路聚合组中启用了…

TikTok矩阵系统的功能展示:深入解析与源代码分享!

今天我来和大家说说TikTok矩阵系统&#xff0c;在当今数字化时代&#xff0c;社交媒体平台已成为人们获取信息、交流思想和娱乐放松的重要渠道&#xff0c;其中&#xff0c;TikTok作为一款全球知名的短视频社交平台&#xff0c;凭借其独特的创意内容和强大的算法推荐系统&#…

【MQ05】异常消息处理

异常消息处理 上节课我们已经学习到了消息的持久化和确认相关的内容。但是&#xff0c;光有这些还不行&#xff0c;如果我们的消费者出现问题了&#xff0c;无法确认&#xff0c;或者直接报错产生异常了&#xff0c;这些消息要怎么处理呢&#xff1f;直接丢弃&#xff1f;这就是…

带大家做一个,易上手的家常蒜香菠菜

一捆 菠菜 四瓣蒜 蒜去皮切末 菠菜切段 多清洗几次 因为菠菜上面的土真的是太多了 菠菜下锅 加水煮一分钟左右 因为菠菜内的草酸成分非常高 所以这一步肯定是要的 然后将菠菜捞出来 干和叶子分开 锅中水倒掉 清洗一下 然后起锅烧油 下蒜末炒香 然后 下菠菜干 因为干熟的…

Python + Selenium —— 网页元素定位之标签名和链接文本定位

tag name tag name 为标签名定位&#xff0c;使用网页元素的标签名如a, div, input, span 等。 但是有一个问题&#xff0c;常见的标签名比如 在同一个页面上有非常多。会不会觉得 tag name 没什么用呢&#xff1f; 当然普通的模拟操作是不大有用&#xff0c;这个重复性实在…

笔记:GO1.19 带来的优化(重新编译juicefs)

## 背景 go编写的应用程序&#xff08;juicefs&#xff09;在k8s&#xff08;docker&#xff09;中运行&#xff0c;时不时出现 OOM Killed。 ## 分析 发现某些应用使用juicefs会导致内存使用飙升&#xff1b; k8s的pod给的内存资源&#xff1a;request 2G&#xff0c;limit…