alin的学习之路(Linux系统编程:五)(目录操作、进程相关概念)

1. 目录操作

1. 查看工作目录 getcwd

char *getcwd(char *buf, size_t size)
功能:获取当前工作目录(绝对路径)参数:buf 保存工作路径的缓冲区size 指定buf可以存储字节数返回值:成功 buf的起始地址失败 NULL
#include <stdio.h>
#include <unistd.h>
#define SIZE 32
int main()
{char buf[SIZE] = {0};char* p = getcwd(buf,SIZE);if(NULL == p){perror("getcwd");return 1;}printf("%s\n",buf);return 0;
}

2. 改变工作目录 chdir

int chdir(const char *path);
功能:改变当前进程工作目录参数:path 相对路径或者绝对路径返回值:成功 0失败 -1
#include <stdio.h>
#include <unistd.h>
#define SIZE 32
int main()
{char buf[SIZE] = {0};char* p = getcwd(buf,SIZE);if(NULL == p){perror("getcwd");return 1;}printf("%s\n",buf);return 0;
}itcast@ubuntu:~/classcode/day05$ ^C
itcast@ubuntu:~/classcode/day05$ cat 2chdir.c
#include <stdio.h>
#include <unistd.h>
#define SIZE 32
#include <string.h>
int main()
{char *p = NULL;char buf[SIZE];memset(buf, 0, SIZE);//获取当前进程工作路径p = getcwd(buf, SIZE);if (NULL == p){perror("getcwd");return 1;}printf("buf: %s\n", buf);int ret = chdir("/home/itcast");if(ret == -1){perror("chdir");return 1;}p = getcwd(buf, SIZE);if (NULL == p){perror("getcwd");return 1;}printf("buf: %s\n", buf);return 0;
}

3.打开目录、关闭目录 opendir\closedir

DIR *opendir(const char *name);
功能:打开目录
参数:name: 目录绝对路径或者相对路径返回值:成功 DIR指针类型失败 NULLint closedir(DIR *dirp);
功能:关闭目录
参数:dirp opendir函数的返回值
返回值:成功 0失败 -1
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>int main()
{DIR * d = NULL;d = opendir("/home/itcast");if(NULL == d){perror("opendir");return 1;}printf("打开目录成功\n");closedir(d);printf("关闭目录成功\n");return 0;
}

4. 读目录 readdir

struct dirent *readdir(DIR *dirp)
功能:读目录
参数:dirp opendir函数的返回值
返回值:成功: 结构体指针失败: NULLstruct dirent {ino_t          d_ino;       /* Inode number */off_t          d_off;       /* Not an offset; see below */unsigned short d_reclen;    /* Length of this record */unsigned char  d_type;      /* Type of file; not supportedby all filesystem types */char           d_name[256]; /* Null-terminated filename */};d_type 文件的类型d_name 文件名
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>int main()
{DIR *dir = NULL;struct dirent* d;//打开目录dir = opendir("/home/itcast");if (NULL == dir){printf("opendir failed...\n");return 1;}while(1){d = readdir(dir);if(d == NULL)break;printf("type: %u, name:%s\n",d->d_type,d->d_name);}closedir(dir);return 0;
}

2.时间相关函数

time_t time(time_t *tloc);
功能:获取时间 从1970年1月1日 00:00:00到现在经历多少秒
参数:tloc time_t类型指针 保存秒数,可以传NULL
返回值:成功 返回秒数 从1970年1月1日 00:00:00到现在经历多少秒失败 -1char *ctime(const time_t *timep);
功能:时间转换函数 将time_t类型的时间转化为字符串
参数:timep time_t指针
返回值:成功 字符串格式的时间struct tm *localtime(const time_t *timep)
功能:将time_t类型的时间转化为struct tm*类型的时间
参数:timep time_t* 类型
返回值:成功 struct tm指针失败 (void*)-1struct tm {int tm_sec;    /* Seconds (0-60) */ 秒int tm_min;    /* Minutes (0-59) */ 分钟int tm_hour;   /* Hours (0-23) */   时int tm_mday;   /* Day of the month (1-31) */ 日int tm_mon;    /* Month (0-11) */ 月int tm_year;   /* Year - 1900 */ 年int tm_wday;   /* Day of the week (0-6, Sunday = 0) */ 星期int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */ 一年中第多少天int tm_isdst;  /* Daylight saving time */};
#include <stdio.h>
#include <time.h>
int main()
{time_t t;  //time_t是long int类型struct tm* tp;t = time(NULL);printf("time = %ld\n",t);printf("ctime = %s\n",ctime(&t));//转化 将秒数转化为年月日时分秒tp = localtime(&t);if ((void*)-1 == tp){perror("localtime");return 1;}printf("tm_sec   %d\n",   tp->tm_sec  );printf("tm_min   %d\n",   tp->tm_min  );printf("tm_hour  %d\n",   tp->tm_hour );printf("tm_mday  %d\n",   tp->tm_mday );printf("tm_mon   %d\n",   tp->tm_mon + 1  );printf("tm_year  %d\n",   tp->tm_year+ 1900 );printf("tm_wday  %d\n",   tp->tm_wday );printf("tm_yday  %d\n",   tp->tm_yday );//asctime函数printf("asctime: %s\n", asctime(tp));//gmtime函数//转化 将秒数转化为年月日时分秒tp = gmtime(&t);if ((void*)-1 == tp){perror("localtime");return 1;}printf("tm_sec   %d\n",   tp->tm_sec  );printf("tm_min   %d\n",   tp->tm_min  );printf("tm_hour  %d\n",   tp->tm_hour + 8);printf("tm_mday  %d\n",   tp->tm_mday );printf("tm_mon   %d\n",   tp->tm_mon + 1  );printf("tm_year  %d\n",   tp->tm_year+ 1900 );printf("tm_wday  %d\n",   tp->tm_wday );printf("tm_yday  %d\n",   tp->tm_yday );return 0;
}

时间相关的函数根据manpage中的函数参数可返回值即可学会它们的使用

3. 进程相关概念及命令

1. 进程概念简述

  1. 进程和程序:

    1. 程序是一个可执行文件
    2. 进程是程序执行的过程
    3. 进程的状态是变化的,包括就绪态,运行态和阻塞态
    4. 进程是管理事务的基本单元。
  2. 单道与多道程序

    1. 单道程序:一个进程运行时其他进程阻塞等待
    2. 多道程序:时钟中断多个进程轮流运行
  3. 并行和并发

    1. 并行:任意时刻多个进程同时执行
    2. 并发:任意时刻仅有一个进程执行,多个进程每个进程执行一小段时间,轮流依次执行
  4. MMU:

    MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统。

  5. 进程控制块PCB

    1. 进程运行时,内核为进程每个进程分配一个PCB(进程控制块),维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。
    2. 其内部成员有很多,我们掌握以下部分即可:
  • 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。
  • 进程的状态,有就绪、运行、挂起、停止等状态。
  • 进程切换时需要保存和恢复的一些CPU寄存器。
  • 描述虚拟地址空间的信息。
  • 描述控制终端的信息。
  • 当前工作目录(Current Working Directory)。
  • umask掩码。
  • 文件描述符表,包含很多指向file结构体的指针。
  • 和信号相关的信息。
  • 用户id和组id。
  • 会话(Session)和进程组。
  • 进程可以使用的资源上限(Resource Limit)。
  1. 进程的状态

    1. 在三态模型中,进程状态分为三个基本状态,即运行态,就绪态,阻塞态

      在五态模型中,进程分为新建态、终止态,运行态,就绪态,阻塞态

  1. **①TASK_RUNNING:**进程正在被CPU执行。当一个进程刚被创建时会处于TASK_RUNNABLE,表示己经准备就绪,正等待被调度。

    ②TASK_INTERRUPTIBLE(可中断):进程正在睡眠(也就是说它被阻塞)等待某些条件的达成。一旦这些条件达成,内核就会把进程状态设置为运行。处于此状态的进程也会因为接收到信号而提前被唤醒,比如给一个TASK_INTERRUPTIBLE状态的进程发送SIGKILL信号,这个进程将先被唤醒(进入TASK_RUNNABLE状态),然后再响应SIGKILL信号而退出(变为TASK_ZOMBIE状态),并不会从TASK_INTERRUPTIBLE状态直接退出。

    ③TASK_UNINTERRUPTIBLE(不可中断):处于等待中的进程,待资源满足时被唤醒,但不可以由其它进程通过信号或中断唤醒。由于不接受外来的任何信号,因此无法用kill杀掉这些处于该状态的进程。而TASK_UNINTERRUPTIBLE状态存在的意义就在于,内核的某些处理流程是不能被打断的。如果响应异步信号,程序的执行流程中就会被插入一段用于处理异步信号的流程,于是原有的流程就被中断了,这可能使某些设备陷入不可控的状态。处于TASK_UNINTERRUPTIBLE状态一般总是非常短暂的,通过ps命令基本上不可能捕捉到。

    **④TASK_ZOMBIE(僵死):**表示进程已经结束了,但是其父进程还没有调用wait4或waitpid()来释放进程描述符。为了父进程能够获知它的消息,子进程的进程描述符仍然被保留着。一旦父进程调用了wait4(),进程描述符就会被释放。

    **⑤TASK_STOPPED(停止):**进程停止执行。当进程接收到SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU等信号的时候。此外,在调试期间接收到任何信号,都会使进程进入这种状态。当接收到SIGCONT信号,会重新回到TASK_RUNNABLE

  2. stat中的参数意义如下:

    参数 含义
    D 不可中断 Uninterruptible(usually IO)
    R 正在运行,或在队列中的进程
    S(大写) 处于休眠状态
    T 停止或被追踪
    Z 僵尸进程
    W 进入内存交换(从内核2.6开始无效)
    X 死掉的进程
    < 高优先级
    N 低优先级
    s 包含子进程
    + 位于前台的进程组
    l 多线种进程(如CLONE_THREAD, NPTL )

2. 进程相关命令

  1. ps 命令:查看当前系统的进程信息

常用选项:-aux 或 -ef

itcast@ubuntu:~/classcode/day05$ ps -aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  1.3 168668 12808 ?        Ss   00:44   0:03 /sbin/in
root           2  0.0  0.0      0     0 ?        S    00:44   0:00 [kthread
root           3  0.0  0.0      0     0 ?        I<   00:44   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   00:44   0:00 [rcu_par
root           6  0.0  0.0      0     0 ?        I<   00:44   0:00 [kworker

可以搭配管道和grep使用,查看指定信息

itcast@ubuntu:~/classcode/day05$ ps -aux | grep bash
itcast      1500  0.0  0.5   8540  5352 pts/0    Ss+  00:58   0:00 -bash
itcast      3689  0.0  0.5   8540  5320 pts/1    Ss   01:46   0:00 -bash
itcast     15277  0.0  0.0   6300   740 pts/1    S+   08:52   0:00 grep --color=auto bash
  1. top命令:动态查看当前系统的进程信息,类似Windows的任务管理器
itcast@ubuntu:~/classcode/day05$ top
top - 08:55:10 up  8:10,  2 users,  load average: 0.00, 0.00, 0.00
Tasks: 190 total,   1 running, 189 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  0.3 sy,  0.0 ni, 99.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.
MiB Mem :    953.3 total,    119.1 free,    242.8 used,    591.4 buff/cache
MiB Swap:   1906.0 total,   1905.2 free,      0.8 used.    549.8 avail MemPID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+754 root       0 -20  161148   7012   6036 S   0.3   0.7   0:35.773461 root      20   0       0      0      0 I   0.3   0.0   0:43.653688 itcast    20   0   13924   5788   4312 S   0.3   0.6   0:00.4115326 itcast    20   0    9248   3784   3260 R   0.3   0.4   0:00.021 root      20   0  168668  12808   8576 S   0.0   1.3   0:03.822 root      20   0       0      0      0 S   0.0   0.0   0:00.013 root       0 -20       0      0      0 I   0.0   0.0   0:00.004 root       0 -20       0      0      0 I   0.0   0.0   0:00.00
  1. kill 命令

    1. 使用方法

      1. kill 进程号
      2. kill -信号编号 进程号
      3. kill -信号宏 进程号
      4. 所以使用kill 必须要得知进程编号,进程编号从ps -aux得来
# sleep second 可以使程序睡眠second秒,用于创建一个进程,并使用kill杀死
# 终端1
itcast@ubuntu:~/classcode/day05$ sleep 1000
Terminated
itcast@ubuntu:~/classcode/day05$ sleep 1000
Killed
itcast@ubuntu:~/classcode/day05$ sleep 1000
Killed# 终端2
itcast@ubuntu:~/classcode/day05$ ps -aux | grep sleep
itcast     15451  0.0  0.0   5476   592 pts/0    S+   08:59   0:00 sleep 1000
itcast     15460  0.0  0.0   6432   664 pts/1    S+   09:00   0:00 grep --color=auto sleep
itcast@ubuntu:~/classcode/day05$ kill 15451
itcast@ubuntu:~/classcode/day05$ ps -aux | grep sleep
itcast     15470  0.0  0.0   5476   596 pts/0    S+   09:00   0:00 sleep 1000
itcast     15474  0.0  0.0   6432   672 pts/1    S+   09:00   0:00 grep --color=auto sleep
itcast@ubuntu:~/classcode/day05$ kill -9 15470
itcast@ubuntu:~/classcode/day05$ ps -aux | grep sleep
itcast     15479  0.0  0.0   5476   592 pts/0    S+   09:00   0:00 sleep 1000
itcast     15481  0.0  0.0   6432   732 pts/1    S+   09:00   0:00 grep --color=auto sleep
itcast@ubuntu:~/classcode/day05$ kill -SIGKILL 15479

例如:杀死sleep进程的三种方法

1. kill 进程号
2. kill -9 进程号
3. kill -SIGKILL 进程号
  1. killall 命令 :杀死指定名称的所有进程
# 终端1
itcast@ubuntu:~/classcode/day05$ sleep 1000 &
[1] 15565
itcast@ubuntu:~/classcode/day05$ sleep 1000 &
[2] 15566
itcast@ubuntu:~/classcode/day05$ sleep 1000 &
[3] 15567# 终端2
itcast@ubuntu:~/classcode/day05$ ps -aux | grep sleep
itcast     15565  0.0  0.0   5476   592 pts/0    S    09:04   0:00 sleep 1000
itcast     15566  0.0  0.0   5476   528 pts/0    S    09:04   0:00 sleep 1000
itcast     15567  0.0  0.0   5476   596 pts/0    S    09:04   0:00 sleep 1000
itcast     15571  0.0  0.0   6432   736 pts/1    S+   09:04   0:00 grep --color=auto sleep
itcast@ubuntu:~/classcode/day05$ killall sleep
itcast@ubuntu:~/classcode/day05$ ps -aux | grep sleep
itcast     15583  0.0  0.0   6432   724 pts/1    S+   09:04   0:00 grep --color=auto sleep

4.进程号相关函数

  1. getpid 获取当前进程进程号
  2. getppid 获取父进程号
  3. getpgid 获取进程组号

与fork搭配看效果

5.创建进程 fork

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t pid = getpid();printf("创建进程前:\n");printf("pid = %d,ppid = %d,pgid = %d\n",getpid(),getppid(),getpgid(pid));fork();printf("创建进程后:\n");printf("pid = %d,ppid = %d,pgid = %d\n",getpid(),getppid(),getpgid(pid));return 0;
}

得到的结果因为子进程在结束之前父进程已经结束,从而子进程的父进程变为/bin/bash,同时getgpid返回

  1. getpid 获取当前进程进程号
  2. getppid 获取父进程号
  3. getpgid 获取进程组号

与fork搭配看效果

5.创建进程 fork

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>int main()
{pid_t pid = getpid();printf("创建进程前:\n");printf("pid = %d,ppid = %d,pgid = %d\n",getpid(),getppid(),getpgid(pid));fork();printf("创建进程后:\n");printf("pid = %d,ppid = %d,pgid = %d\n",getpid(),getppid(),getpgid(pid));return 0;
}

得到的结果因为子进程在结束之前父进程已经结束,从而子进程的父进程变为/bin/bash,同时getgpid返回

alin的学习之路(Linux系统编程:五)(目录操作、进程相关概念)相关推荐

  1. Linux系统编程.NO7——目录操作函数

    5. 目录文件管理函数 5.1. 目录文件概念 目录在Linux中也是文件,也有对应的文件指针,每次读目录之前也要先打开目录,然后目录指针就出现了,第一次读就是第一个文件的信息,然后第二次读就是第二个 ...

  2. Linux系统编程(三)进程间的通信

    Linux系统编程(三)进程间的通信 一.为什么需要进程之间的通信(IPC)? 二.管道 1.概念 2.特质 3.原理 4.局限性 5.代码 2.读入数据 三.共享存储映射 注意事项 父子进程通信 一 ...

  3. 【学习笔记】Linux 系统编程入门

    Linux 系统编程入门 静态库与动态库 静态库命名规则 静态库的制作 静态库使用 动态库制作 动态库使用 加载动态库 静态库的优缺点 动态库的优缺点 Makefile 文件命名 工作原理 变量 模式 ...

  4. 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)

    文章目录 Linux系统编程 文件IO open/close函数 read/write函数 文件描述符 阻塞.非阻塞 fcntl函数 lseek函数 传入传出参数 文件系统 文件存储 文件操作 sta ...

  5. Linux系统编程-文件的操作

    Linux系统编程-文件操作 前言: Linux 中所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,硬件设备(键盘.监视器.硬盘.打印机)是文件,就连套接字(socket).网络通 ...

  6. 初始Linux—Linux系统编程第三节——初始进程

    目录 冯 · 诺依曼体系结构 操作系统:Operator System(OS) 进程的基本概念 进程标识符 通过系统调用创建进程-fork初识 进程状态 僵尸进程 孤儿进程 进程优先级 环境变量 和环 ...

  7. 【Linux系统编程】浅谈进程地址空间与虚拟存储空间

    早期的内存分配机制 在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址.当计算机同时运行多个程序时,必须保证这些 ...

  8. 嵌入式学习之Linux系统编程---9 目录IO之readdir函数

    1.readdir函数的函数原型 #include <dirent.h> struct dirent *readdir(DIR *dirp); 对于readdir函数来说,它只有目录流指针 ...

  9. Linux系统编程 | 01 -文件操作

    一.文件操作方法 linux中有两种方法可以操作文件:系统调用和c库函数. 1. 什么是系统调用? 由操作系统实现并提供给外部应用程序的编程接口(API),是应用程序同系统之间数据交互的桥梁. C标准 ...

  10. 【Linux系统编程】线程与进程的比较

    在许多经典的操作系统教科书中,总是把进程定义为程序的执行实例,它并不执行什么, 只是维护应用程序所需的各种资源,而线程则是真正的执行实体. 为了让进程完成一定的工作,进程必须至少包含一个线程. 进程, ...

最新文章

  1. 计算机网络实验可变长子网掩码,计算机网络实验3-子网掩码与划分子网实验报告.docx...
  2. mysql从零开始自增id_MySQL从零开始 7-表约束之主键,自增长,唯一键
  3. 【程序员必看】如何用Python从0开始创建一个区块链?
  4. Android事件分发机制之ACTION_DOWN
  5. Mysql字符串截取 mysql将字符串字段转为数字排序或比大小
  6. 从北京回来的年轻人,我该告诉你点什么?
  7. Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)
  8. Python风格总结:ASCII码与字符相互转换
  9. redis linux工具安装,linux 安装redis缓存工具
  10. C++判断一个序列是否为堆(最大堆、最小堆)
  11. 迅为iTOP-4412核心板调整电压
  12. IMU(陀螺仪)角速度测量原理-科氏力测旋转角速度
  13. 虚拟机ubuntu的联网方法(NET)
  14. Android布局总汇篇(XXXLayout)
  15. BUUCTF中的reverse2
  16. MCU学习——无线遥控模块
  17. Bean Definition到底是什么,附spring思维导图分享
  18. 四旋翼无人机学习第4节--STM32、MPU9250等器件的绘制
  19. 无准考证号的四六级查询
  20. HBase 数量统计

热门文章

  1. 经销商激励政策、策略、方案、手段、方法、措施
  2. 多元正态分布(Multivariate normal distribution)
  3. 【小程序测试】接口测试
  4. Ubuntu20.04 安装python3.6
  5. 2022年1月7日对自己近况的一次总结
  6. 网工日常必备思科华为设备命令对照表,全网最完整
  7. Ubuntu终端代理工具——proxychains
  8. VLAD特征(vector of locally aggregated descriptors)
  9. socket(四)–组播
  10. android仿微信发布动态功能,Android 类似微博、微信展示动态(Feed)的WeiBoLayout