APUE第七章学习笔记

本文介绍了进程终止的不同方式,包括_exit、_Exit 和 exit 函数的区别,并通过示例代码展示了如何使用 atexit 函数注册终止处理程序。此外,还详细解释了环境变量的操作,如获取、设置和删除环境变量的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一: 进程终止

/*********************************************************
退出函数:
包含头文件:  #include <stdlib.h>
函数原型:       void exit(int status);
                void  _Exit(int status);
包含头文件:  #include <unistd.h>
函数原型:   void _exit(int status);
函数说明: 用于正常终止程序,_exit和_Exit立即进入内核,exit则先执行一些清理处理,然后返回内核
***********************************************************/
/***********************************************************
包含头文件:  #include <stdlib.h>
函数原型:   int atexit(void (*func)(void));
函数说明:    用于注册终止处理程序
注: exit调用终止处理程序顺序与注册顺序相反,同一函数登记多次,也会被调用多次
返回值:若成功,返回0,若出错,返回非0
***********************************************************/

vi 7.1.c

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

//  终止程序假设执行 clean gather erase等操作

void clean()
{
    printf("程序已经终止,请让我来清理垃圾吧!\n");
}

void gather()
{
    printf("垃圾清理完毕,让我来收集打包垃圾吧!\n");
}

void erase()
{
    printf("垃圾打包完毕,让我来移除垃圾吧!\n");
}

int main()
{
    if (atexit(erase))
    {
    printf("register remove failed\n");
    return 0;
    }
    if  (atexit(gather))
    {
    printf("register gather failed\n");
    exit(0);
    }

    if (atexit(clean))
    {
    printf("register clean failed\n");
    exit(0);
    }
    return 0;
}

这里写图片描述

/*****************************************************
存储空间分配:
包含头文件:  #include <stdlib.h>
函数原型:   void *malloc(size_t size);
            void *calloc(size_t nobj,size_t size);
            void *realloc(void *obj,size_t size);
函数说明:  (1)  malloc: 分配size个字节的空间
               (2)  calloc:   给指定长度对象分配空间,每个bit初始化为0
(3)  realloc : 分配size个字节的空间,并将obj移入分配空间内
返回值: 若成功,返回指针,若失败,返回NULL
 void free(void* ptr)
函数说明: 释放ptr指向的空间
********************************************************/
/*********************************************************
环境表:
每个程序都可以得到环境变量,进程接受到环境表,环境表是一个字符指针数组,Unix系统提供了全局变量
    char ** environ 指向该指针数组         
************************************************************/
/**************************************************************
包含头文件:  #include <stdlib.h>
函数原型:   char* getenv(const char* name);
函数说明: 得到环境变量name对应的value
返回值:  若找到,返回value的字符指针,若无,返回NULL
**********************************************************/
/*********************************************************
包含头文件:  #include <stdlib.h>
函数原型:   int putenv(char *str);
函数说明: 取形式为name = value的字符串,将其放到环境表,如果name已存在,则先删除其原来的定义
返回值: 若成功,返回0,若出错,返回非0
**********************************************************/
/********************************************************
包含头文件:  #include <stdlib.h>
函数原型:   int setenv(const char* name,const char* value,int rewrite);
函数说明: 增加或修改环境变量 name = value(若
rewrite非0,则删除其现有的定义;若rewrite为0,则不删除其现有定义(name 不设置为value,而且也不会出错)
返回值: 若成功,返回0,若失败,返回-1
***********************************************************/
/****************************************************
包含头文件:  #include <stdlib.h>
函数原型:   int unsetenv(const char* name);
函数说明:  删除环境变量name的定义,即使name不存在也不会出错
返回值:  若成功,返回0,若失败,返回-1
**********************************************/

vi 7.2.c

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

int main()
{

    char* start_dir;

    if ((start_dir = getenv("HOME")) == NULL)
    {
    printf("getenv error\n");
    exit(0);
    }

    printf("home起始目录:  %s\n",start_dir);
    return 0;
}

这里写图片描述

vi 7.3.c

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

int main()
{
    char* envname = "Marco";
    char* envvalue = "帅哥";

    if (setenv(envname,envvalue,1) < 0)
    {
    printf("setenv error\n");
    exit(0);
    }

    char* exist;

    if ((exist = getenv(envname)) == NULL)
    {
    printf("环境变量不存在\n");
    exit(0);
    }

    printf("环境变量Marco值是:  %s\n",envvalue);

    if (unsetenv(envname) < 0)
    {
    printf("删除Marco环境变量失败\n");
    exit(0);
    }
    else
    printf("删除Marco环境变量成功\n");
    return 0;
}

这里写图片描述

/***************************************************
包含头文件: #include

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

#define IN_JMP 1
#define HANDLE_JMP 2
#define OUT_JMP 3

int in_error = 1;
int handle_error = 1;
int out_error = 1;
jmp_buf jmp;

// 假设程序步骤为  进入(in)  处理(handle)  出去(out)

void In()
{
    if (in_error)
    {
    longjmp(jmp,IN_JMP);
    }
    printf("In 完成\n");
}

void Handle()
{
    if (handle_error)
    {
    longjmp(jmp,HANDLE_JMP);
    }
    printf("Handle 完成\n");
}

void Out()
{
    if (out_error)
    {
    longjmp(jmp,OUT_JMP);
    }
    printf("Out 完成\n");
}

int main()
{

    if (setjmp(jmp) == IN_JMP)
    {
    printf("进入出错\n");
    in_error = 0;
    }

    In();
    if (setjmp(jmp) == HANDLE_JMP)
    {
    printf("处理错误\n");
    handle_error = 0;
    }
    Handle();
    if (setjmp(jmp) == OUT_JMP)
    {
    printf("出去错误\n");
    out_error = 0;
    }
    Out();
    return 0;
}

这里写图片描述

/*********************************************************
包含头文件:  #include <sys/resource.h>
函数原型:   int getrlimit(int resource,struct rlimit *rlptr);
            int setrlimit(int resource,struct rlimit *rlptr);
参数说明: int resource:由系统定义的一些资源限制种类
struct rlimit: struct rlimit
{
    rlim_t rlim_cur;   //软限制值:  当前限制值
    rlim_t rlim_max;  //硬限制值:   软限制值的最大值
}
函数说明:  得到或设置 软限制值和硬限制值 
*********************************************************/
### APUE 第三章 学习笔记 #### 文件 I/O 基础 APUE 的第三章主要讨论了 Unix 系统中的文件 I/O 操作基础。这一章节涵盖了多个重要的概念和技术细节,对于理解如何高效地操作文件至关重要。 #### 打开和关闭文件 为了打开一个文件,程序通常会使用 `open` 或者 `creat` 函数[^1]。这两个函数都返回一个小于零的整数作为错误指示,而成功的调用则返回一个非负整数表示新创建的文件描述符。当不再需要访问某个特定文件时,应该通过调用 `close` 来关闭它。这不仅释放了与该文件关联的操作系统资源,而且也使得这个文件描述符能够被重新利用。 ```c #include <fcntl.h> /* For O_* constants */ #include <unistd.h> /* For open(), close() */ int fd; fd = open("example.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd >= 0) { // File opened successfully. } // Later... close(fd); ``` #### 文件读写 一旦有了有效的文件描述符,就可以对其进行读取 (`read`) 和写入 (`write`) 操作。这些基本的 I/O 操作允许应用程序直接处理底层的数据流而不必关心具体的设备特性[^2]。 ```c char buffer[BUFSIZ]; ssize_t n; n = read(fd, buffer, BUFSIZ - 1); if (n > 0) { buffer[n] = '\0'; // Null terminate the string printf("%s\n", buffer); } const char *msg = "Hello world!"; write(fd, msg, strlen(msg)); ``` #### 文件定位 除了简单的顺序读写外,还可以改变当前文件偏移量来实现随机访问。这是通过 `lseek` 实现的功能之一,它可以向前或向后移动文件指针的位置以便从不同的位置开始读写数据[^3]。 ```c off_t offset; offset = lseek(fd, SEEK_SET, 0); // Move to beginning of file if (offset != -1L) { // Seek succeeded. } ``` #### 特殊文件类型的支持 Unix 系统支持多种特殊类型的文件对象,比如管道、套接字以及终端设备等。本章还介绍了针对这些不同类型文件的具体 API 接口和支持机制[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值