Linux系统编程(三)—— 文件编程(3)进程环境

news2024/11/24 10:25:45

一、main函数

  • 现在的格式:int main(int argc, char *argv[])
  • 以前的main函数有三个参数,另一个参数就是环境变量

二、进程的终止(两种都要背下来)

2.1 正常终止

(1)从main函数返回

  • main函数被称为程序的入口
  • 许多人写的:return 0
  • 注意:进程的返回值是给父进程看的
  • 面试题:
#include <stdio.h>
#include <stdlib.h>

int main() {

    printf("hello!\n");

    return 0;
}

该进程的父进程为:shell
可以利用:echo $?查看上一条语句的执行状态
在这里插入图片描述
当程序变为下面的样子:
在这里插入图片描述
问题:父进程看到子进程的退出状态为多少?
这里应该是:7
因为printf返回值为7(打印了7个字符)

(2)调用exit

  • exit( )是库函数
  • 例如程序里面写的:exit(0);
  • exit( )可以返回256种状态(-128 到 127):
    在这里插入图片描述
  • 会调用钩子函数:
    在这里插入图片描述

补充:atexit( )函数:钩子函数

  • 钩子函数特别像C++中的析构函数
    在这里插入图片描述
  • 钩子函数的调用是以当初声明函数的逆序方式调用的
  • 例子:
#include <stdio.h>
#include <stdlib.h>

static void f1(void) {
    puts("f1() is working");
}

static void f2(void) {
    puts("f2() is working");
}

static void f3(void) {
    puts("f3() is working");
}

int main() {
    puts("Begin");

    atexit(f1);
    atexit(f2);
    atexit(f3);

    puts("End");

    exit(0);
}

运行结果:
在这里插入图片描述

(3)调用_exit或_Exit

  • _exit( )和_Exit是系统调用函数,exit( )是库函数,这是依赖与前面两个系统调用函数的。
    在这里插入图片描述
  • exit( )和_exit( )的区别:
    1)_exit( )是直接结束进程(不执行钩子函数,不进行I/O清理)
    2)exit( )要先去终止处理程序,标准I/O清理程序,然后才依赖与_exit( )去结束进程

(4)最后一个线程从其启动例程返回

(5)最后一个线程调用pthread_exit

2.2 异常终止

(1)调用abort

(2)接到一个信号并终止

(3)最后一个线程对其取消请求作出响应

三、命令行参数的分析

几乎shell命令行解析都是这俩函数解决的:

(1)getopt( )函数

在这里插入图片描述

  • getopt( )函数:是用来解析命令行选项参数的,但是只能解析短格式:ls -a ,不能解析长格式:ls --all (可以用getopt_long( )解析长格式)

  • 参数介绍:
    (1)argc:main()函数传递过来的参数的个数
    (2)argv:main()函数传递过来的参数的字符串指针数组
    (3)optstring:选项字符串,告知 getopt()可以处理哪个选项以及哪个选项需要参数

  • 返回值:如果选项成功找到,返回选项字母;如果所有命令行选项都解析完毕,返回 -1;如果遇到选项字符不在 optstring 中,返回字符 ‘?’

  • optstring的格式:
    对于格式:char*optstring = “-dab:c::”;

    (1)单个字符 a 表示选项 a 没有参数
    格式:-a 即可,不加参数

    (2)单字符加冒号b: 表示选项b有且必须加参数
    格式:-b 100或-b100,但-b=100错

    (3)单字符加两个冒号 c:: 表示选项c可以有,也可以无
    格式:-c200,其它格式错误

    (4)如果在第一个符号是 ’-‘,这表明有有非选项传参,返回值为 1

  • 当检查到上面某一个参数被指定时,函数会返回被指定的参数名称(即该字母):
    (1)optarg —— 指向当前选项参数(如果有)的指针。
    (2)optind —— 再次调用 getopt() 时的下一个 argv指针的索引。
    (3)optopt —— 最后一个未知选项。
    (4)opterr ­—— 如果不希望getopt()打印出错信息,则只要将全域变量opterr设为0即可。

具体案例:mydate.c
按照指定格式打印时间,可以通过非选项传参,指定是否将时间打印到指定文件当中去

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <string.h>

/*
    -y: year
    -m: month
    -d: day
    -H: hour
    -M: minute
    -S: second
*/

#define TIMESTRSIZE 1024
#define FMTSTRSIZE 1024

int main(int argc, char **argv) {
    time_t stamp;
    struct tm *tm;
    char timestr[TIMESTRSIZE];
    int c;
    char fmtstr[FMTSTRSIZE];
    FILE *fp = stdout;

    fmtstr[0] = '\0';

    stamp = time(NULL);
    tm = localtime(&stamp);
    
    while (1) {
        c = getopt(argc, argv, "-H:MSy:md");
        if (c < 0)
            break;

        switch (c) {
            case 1:
                if (fp == stdout) {
                    fp = fopen(argv[optind - 1], "w");
                    if (fp == NULL) {
                        perror("fopen()");
                        fp = stdout;
                    }
                }
                break;
            case 'H':
                if (strcmp(optarg, "12") == 0)
                    strncat(fmtstr, "%I(%P) ", FMTSTRSIZE);
                else if (strcmp(optarg, "24") == 0)
                    strncat(fmtstr, "%H ", FMTSTRSIZE);
                else
                    fprintf(stderr, "Invalid argument of -H \n");
                break;
                      case 'M':
                strncat(fmtstr, "%M ", FMTSTRSIZE);
                break;
            case 'S':
                strncat(fmtstr, "%S ", FMTSTRSIZE);
                break;
            case 'y':
                if (strcmp(optarg, "2") == 0)
                    strncat(fmtstr, "%y ", FMTSTRSIZE);
                else if (strcmp(optarg, "4") == 0)
                    strncat(fmtstr, "%Y ", FMTSTRSIZE);
                else
                    fprintf(stderr, "Invalid argument of -y \n");
                break;
            case 'm':
                strncat(fmtstr, "%m ", FMTSTRSIZE);
                break;
            case 'd':
                strncat(fmtstr, "%d ", FMTSTRSIZE);
                break;
            default:
                break;
        }
    }
    strncat(fmtstr, "\n", FMTSTRSIZE);
    strftime(timestr, TIMESTRSIZE, fmtstr, tm);
    fputs(timestr, fp);

    if (fp != stdout)
        fclose(fp);

    exit(0);
}

讲解:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
运行结果:
在这里插入图片描述

(2)getopt_long( )函数:分析长格式:ls --all

四、环境变量

  • 本质:KEY = VALUE形式

(1)export命名

  • 利用:export 命令可以查看当前的环境变量
    在这里插入图片描述
  • 粗浅的理解环境变量:把当前的操作系统比作正在跑的程序,环境变量就是该程序的全局变量。

(2)environ全局变量

在这里插入图片描述
例子:myenv.c
打印环境变量

#include <stdio.h>
#include <stdlib.h>

extern char **environ;

int main() {
    
    int i;
    for (i = 0; environ[i] != NULL; i++) {
        puts(environ[i]);
    }

    exit(0);
}

运行结果:
在这里插入图片描述

(3)getenv( )函数:获取环境变量

在这里插入图片描述
例子:getenv.c
获取 PATH 这个环境变量

#include <stdio.h>
#include <stdlib.h>

int main() {
    puts(getenv("PATH"));

    exit(0);
}

运行结果:
在这里插入图片描述

(4)setenv( )函数:改变或者添加环境变量

在这里插入图片描述

(5)putenv( )函数:改变或者添加环境变量

在这里插入图片描述

五、C程序的存储空间布局

  • 假设用的32位环境,虚拟空间是4G
    在这里插入图片描述

六、库

(1)动态库

(2)静态库

(3)手工装载库

  • 类似于pthotoshop软件打开会加载很多库,如果其中其中某一个库加载失败了,程序也不会结束,而是会进行运行,只不过那个库不能使用了
  • 这里可以看man手册当中关于:dlopen( )函数的讲解以及后面的例子

七、函数跳转

注意:goto语句不能跨函数的跳转,此时可以用 setjmp( ) 函数和 longjmp( )函数实现跨函数跳转

(1)setjmp( )函数:设置跳转点

(2)longjmp( )函数:从某一位置跳转到某个跳转点

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

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

相关文章

第10章:堆

堆是什么&#xff1f; 堆是一种特殊的完全二叉树。 完全二叉树&#xff1a;每层节点都完全填满&#xff0c;最后一层若是没填满&#xff0c;则只缺少右边的节点。所有的节点都大于等于&#xff08;最大堆&#xff09;或小于等于&#xff08;最小堆&#xff09;它的子节点。jav…

软考——数据结构,算法基础,程序设计语言,法律法规,多媒体基础

数据结构与算法基础 数组与矩阵线性表广义表树与二叉树图排序与查找算法基础及常见算法 数组 稀疏矩阵 直接把&#xff08;0&#xff0c;0&#xff09;带入&#xff0c;排除B&#xff0c;C 将&#xff08;1&#xff0c;1&#xff09;带入&#xff0c;排除D&#xff0c; 最终…

Python | 人脸识别系统 — 博客索引

本博客为人脸识别系统的博客索引 工具安装、环境配置&#xff1a;Python | 人脸识别系统 — 简介 1、UI代码 UI界面设计&#xff1a;Python | 人脸识别系统 — UI界面设计UI事件处理&#xff1a;Python | 人脸识别系统 — UI事件处理 2、用户端代码 用户端博客索引&#xff1a;…

Jupyter Notebook入门教程

Jupyter Notebook&#xff08;又称Python Notebook&#xff09;是一个交互式的笔记本&#xff0c;支持运行超过40种编程语言。本文中我们将介绍Jupyter Notebook的主要特点&#xff0c;了解为什么它能成为人们创造优美的可交互式文档和教育资源的一个强大工具。 首先&#xff…

vue diff算法与虚拟dom知识整理(4) h函数虚拟节点嵌套

那么 先补充上文有一个没强调的点 h函数 当你不需要属性时 其实是可以不传的 例如 我们打开案例 打开 src下的index.js 修改代码如下 import {init,classModule,propsModule,styleModule,eventListenersModule,h,} from "snabbdom";//创建patch函数const patch ini…

CUBLAS 和 CUDNN

文章目录 一、什么是CUBLASCUBLAS实现矩阵乘法CUBLAS中的Leading DimensionCUBLAS LEVEL3函数 &#xff1a; 矩阵矩阵CUBLAS实现矩阵乘法 二、cuDNN使用CuDNN实现卷积神经网络 四、CUBLAS和CUDNN实践 一、什么是CUBLAS cuBLAS是BLAS的一个实现。BLAS是一个经典的线性代数库&am…

解决C语言的缺陷【C++】

文章目录 命名空间展开了命名空间域指定访问命名空间域域作用限定符命名空间定义 C输入&输出缺省参数全缺省参数半缺省参数缺省参数应用 函数重载参数类型不同参数个数不同参数类型顺序不同 引用引用的特性引用在定义时必须初始化一个变量可以有多个引用引用一旦引用一个实…

基于Radon-分数傅里叶变换对消器的海杂波弱目标检测

海面微弱目标检测面临的主要困难来自&#xff1a; 慢速小目标回波微弱&#xff1b;空时变海杂波异常复杂&#xff0c;海杂波特性认知难度大&#xff1b;目标模型难以建立&#xff1b;目标、海杂波类别非平衡。 ARU效应 是由于海面波浪的起伏和涟漪引起的。在雷达回波信号中&am…

nodejs开发 | 安全工具端口扫描器

今天分享一个nodejs的demo&#xff0c;可以扫描出指定IP的端口开放情况。 简单的说 Node.js 就是运行在服务端的 JavaScript。 Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台。 Node.js 是一个事件驱动 I/O 服务端 JavaScript 环境&#xff0c;基于 Google 的 V8…

[笔记]Python计算机视觉编程《一》 基本的图像操作和处理

文章目录 前言环境搭建 计算机视觉简介Python和NumPy第一章 基本的图像操作和处理1.1 PIL&#xff1a;Python图像处理类库1.1.1 转换图像格式1.1.2 创建缩略图1.1.3 复制和粘贴图像区域1.1.4 调整尺寸和旋转 1.2 Matplotlib1.2.1 绘制图像、点和线 前言 今天&#xff0c;图…

python基础实战6-python字符串

1字符串的表达方式 字符串是 Python 中最常用的数据类型。我们可以使用引号 ( 或 " ) 来创建字符串。 字符串表达方式 a " I m Tom" #一对双引号 b ’Tom said:" I am Tom" #一对单引号 c ‘Tom said: " I\m Tom" #转义字符 d T…

python库,科学计算与数据可视化基础,知识笔记(numpy+matplotlib)

文章目录 1、numpyndarray对象&#xff0c;数组指定形状创建&#xff08;要会&#xff09;数组的索引&#xff0c;切片与遍历&#xff08;要会&#xff09;数组的相加&#xff0c;转置&#xff0c;展开&#xff08;要会&#xff09;数组元素增删改查&#xff08;最好会&#xf…

当CRM遇见ChatGPT,AI如何帮销售打造“最强大脑”

导读&#xff1a;这一轮AI浪潮将对CRM企业带来哪些新机遇&#xff1f; ChatGPT诞生至今不过100多天&#xff0c;但它已经对很多行业产生了巨大影响。 企业直面市场的一线战场——销售、营销、客服等领域也是如此。以ChatGPT为代表的人工智能技术热潮正在改变着传统营销、销售的…

MySQL--group by--聚合函数--内置函数--0415 22

目录 1.聚合函数 1.1 count 1.2 sum 1.3 avg 1.4 max 和 min 2. group by 2.1 group by 的条件筛选——having 2.2 总结 3.日期函数 4.字符串函数 concat replace substring 以首字母大写&#xff0c;其余字母小写的方式显示员工的姓名 5.数学函数 format rand()…

C plus plus ——【继承与派生】

系列文章目录 C plud plus ——【面向对象编程】 C plus plus ——【继承与派生】 文章目录 系列文章目录前言一、继承1.1 类的继承1.2 继承后可访问性1.3 构造函数访问顺序1.4 子类隐藏父类的成员函数 二、重载运算符2.1重载运算符的必要性2.2重载运算的形式与规则2.3 转换运…

数字信号处理学习1

基本上算是没怎么学过数字信号处理这门课&#xff0c;因为本科的时候&#xff0c;专业方向用不上&#xff0c;现在没法子了&#xff0c;专业使然&#xff0c;只能自己自学了&#xff0c;但是我又不知道该从何学起&#xff0c;就买了一本现代数字信号处理&#xff0c;结果发现人…

数据结构/队列实现栈

前言 在学习数据结构的过程当中&#xff0c;我们会学到栈和队列&#xff0c;在本篇文章中&#xff0c;重点讲解的是队列实现栈&#xff0c;在上篇文章中已经简单介绍过栈和队列的使用说明&#xff0c;以及栈实现队列。(2条消息) 数据结构/栈实现队列_Y君的进化史的博客-CSDN博客…

吴恩达ChatGPT网课笔记Prompt Engineering——训练ChatGPT前请先训练自己

吴恩达ChatGPT网课笔记Prompt Engineering——训练ChatGPT前请先训练自己 主要是吴恩达的网课&#xff0c;还有部分github的prompt-engineering-for-developers项目&#xff0c;以及部分自己的经验。 一、常用使用技巧 prompt最好是英文的&#xff0c;如果是中文的prompt&am…

Day961.老城区前端改造 -遗留系统现代化实战

老城区前端改造 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于老城区前端改造的内容。 什么是“改造老城区”。改造老城区模式 是指对遗留系统内部的模块进行治理&#xff0c;让模块内部结构合理、模块之间职责清晰的一系列模式。 也就是说&#xff0c;在遗留系统…

【Redis】聊一下Redis基础架构

我们知道学习一个技术&#xff0c;最好的方式就是从全局观出发&#xff0c;然后针对不同的点进行拆分&#xff0c;一个个破解。既可以将学到的和已有的知识联系起来&#xff0c;又可以有一定的深度和目的性。 Redis基础架构 对于一个中间件来说&#xff0c;一个是使用层面&…