UNIX 高级编程学习记录-概述

基本信息

1、程序
程序是一个存储在磁盘某个目录上的可执行文件,内核使用exec函数将程序读入内存,并执行程序。

2、进程
进程是程序执行的实例 ,用于控制进程的有3个主要的函数。 fork() 、 exec() 、 waitpid()
exec函数有7种变体。但它们总称为exec函数。

3、线程
通常情况下,一个进程只有一个控制线程。
也可以多个控制线程可以充分利用多处理器系统的并行能力。
一个进程内所有的线程共享同一地址空间、文件描述符、栈以及与进程相关属性。因为它们能访问同一存储区,所以各线程在访问共享数据时需要采取同步措施以避免不一致性。
与进程类似,线程也用ID 标识,但线程的ID 只在它所属的进程内起作用。我们可以使用改线程ID 引用它。进行处理。线程ID 只在它所属的进程内有意义。

出错处理

在C语言头文件 <errno.h> 中定义了出错的状态码和出错原因
在Ubuntu 系统中, 头文件 errno.h 位于 /usr/include/asm-generic/errno.h

打开errno.h头文件,可以看到变量对应的出错情况。下图是截取的部分宏。在百度百科里也有相关说明。
在这里插入图片描述
百度百科部分内容
在这里插入图片描述

在C语言中定义了两个标准函数用来输出错误出错消息。

//1
#include <string.h>
char * strerror(int errnum);

errnum 通常是errno 的值 ,strerror映射为对应出错的消息。并返回指向此字符串的指针。

//2
#include <stdio.h>
void perror(const char *msg);

perror 是根据errno 的当前 值进行输出对应的出错消息。
输出结果为 先输出 msg 指向的字符串 ,然后冒号 之后出错的消息,最后换行符。

  1 #include <stdio.h>
  2 #include <errno.h>
  3 #include <string.h>
  4 int main(int argc, char *argv[])
  5 {
  6     fprintf(stderr,"EACCES: %s\n", strerror(EACCES));
  7     errno = 39;   //或者 errno = ENOTEMPTY
  8     perror(argv[0]);
  9     return 0;
 10 }

输出结果为:
在这里插入图片描述

可根据输出来判断程序出错的原因,及时进行处理,排除故障。或者对可能的出错进行判断,防止程序崩溃,提高程序的健壮性。

用户标识

用户ID,是用来标识各个不同的用户的。
组ID , 用来标识用户的属组。
组文件将组名 映射为 组ID 可以在 /etc/group 中查询。

利用程序获取用户ID 和组ID
包含头文件 <unisted.h>
getuid() 获取用户ID getgid() 获取用户组ID。

#include <unisted.h>
int main()
{
     printf("%d, %d\n", getuid(), getgid());
     return 0;
} 

信号

信号用于通知 进程发生了某种情况
进程有以下三种处理信号的方式
1、忽略信号。
2、按系统默认方式处理。终止进程。
3、提供一个函数,信号发生时调用函数。

终端键盘上有两种产生信号的方法。 中断键(CRTl + C ) 或者退出键(CTRL + \ ) 它们被用于中断当前运行的进程。

也可使使用kill 函数。在一个进程里向另一个进程发送一个信号。

为了捕捉到信号,程序需要调用signal 函数 , 其中指定了当产生SIGINT 信号时,要调用的函数名字。

if (signal(SIGINT, sig_int) == SIG_ERR)
{
      printf ("signal error\n");
}

在程序运行时使用键盘输入 CTRL + c 进程使用signal 函数接受到SIGINT 后没有按照默认方式结束进程。而是使用sig_int 函数去处理。由于除于循环之中,所以无法通过CTRL + c 关闭程序。
需要包含 头文件 #include <signal.h>
在这里插入图片描述
图片来源于博客 https://blog.csdn.net/fengbingchun/article/details/92074191

时间值

1、日历时间
日历时间从1970 年 1号 0 点开始,以秒计算。可以通过时区得到本地时间 使用tm 结构体可以获取 秒数 对应的详细时间。
2、进程时间,也被称为CPU 时间 。用以度量进程使用的中央处理器资源。
当度量一个进程执行的时间时,Unix 系统为一个进程维护了3个进程时间值。
a、时钟时间
b、用户CPU时间
c、系统CPU时间

时钟时间又称为墙上时钟时间,它是进程运行的时间总量,其值与系统中同时运行的进程数有关。
用户CPU时间是执行用户指令所用的时间量。
系统CPU时间是为该进程执行内核程序所经历的时间。为了获取一个进程的进程时间可以使用shell 命令 time

$ time date
在这里插入图片描述

第一章相关代码

使用相关头文件
#include <unistd.h> fork() execlp () 函数
#include <stdlib.h> exit()
#include <wait.h> waitpid()函数头文件
#include <errno.h> errno 变量

    1 #include <stdio.h>
    2 #include <wait.h>
    3 #include <string.h>
    4 #include <unistd.h>
    5 #include <stdlib.h>
    6 #include <signal.h>
    7 static void sig_int()
    8 {
    9     printf("sig_int error\n");
   10 }
   11 
   12 
   13 int main()
   14 {
   15 
   16     char buf[200];
   17     pid_t pid;
   18     int status;
   19 
>> 20      if (signal(SIGINT, sig_int) == SIG_ERR)
   21          printf ("signal error\n");
   22 
   23      printf("%%");
   24 
   25      while (fgets(buf, 200, stdin) != NULL)
   26      {
   27           if (buf[strlen(buf) -1] == '\n')
   28               buf[strlen(buf) - 1] = 0;
   29 
   30 
   31          if ((pid = fork()) < 0)
   32          {
   33              printf("fork error\n");
   34          } else if (pid == 0)
   35          {
   36              execlp(buf, buf, (char*)0);
   37              printf("couldn`t execute: %s", buf);
   38              exit(127);
   39          }
   40          if ((pid = waitpid(pid,&status, 0)) < 0)
   41              printf("waitpid error");
   42          printf("%%");
   43      }
   44      return 0;
   45  }

注意 程序运行后,无法使用 CTRL + c 关闭。因为会signal 会捕获这个信号,并调用sig_int 函数处理。不会以默认方式退出。可以使用 CTRL + \ 退出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值