alin的学习之路(Linux系统编程:五)(目录操作、进程相关概念)
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. 进程概念简述
进程和程序:
- 程序是一个可执行文件
- 进程是程序执行的过程
- 进程的状态是变化的,包括就绪态,运行态和阻塞态
- 进程是管理事务的基本单元。
单道与多道程序
- 单道程序:一个进程运行时其他进程阻塞等待
- 多道程序:时钟中断多个进程轮流运行
并行和并发
- 并行:任意时刻多个进程同时执行
- 并发:任意时刻仅有一个进程执行,多个进程每个进程执行一小段时间,轮流依次执行
MMU:
MMU是Memory Management Unit的缩写,中文名是内存管理单元,它是中央处理器(CPU)中用来管理虚拟存储器、物理存储器的控制线路,同时也负责虚拟地址映射为物理地址,以及提供硬件机制的内存访问授权,多用户多进程操作系统。
进程控制块PCB
- 进程运行时,内核为进程每个进程分配一个PCB(进程控制块),维护进程相关的信息,Linux内核的进程控制块是task_struct结构体。
- 其内部成员有很多,我们掌握以下部分即可:
- 进程id。系统中每个进程有唯一的id,在C语言中用pid_t类型表示,其实就是一个非负整数。
- 进程的状态,有就绪、运行、挂起、停止等状态。
- 进程切换时需要保存和恢复的一些CPU寄存器。
- 描述虚拟地址空间的信息。
- 描述控制终端的信息。
- 当前工作目录(Current Working Directory)。
- umask掩码。
- 文件描述符表,包含很多指向file结构体的指针。
- 和信号相关的信息。
- 用户id和组id。
- 会话(Session)和进程组。
- 进程可以使用的资源上限(Resource Limit)。
进程的状态
在三态模型中,进程状态分为三个基本状态,即运行态,就绪态,阻塞态。
在五态模型中,进程分为新建态、终止态,运行态,就绪态,阻塞态。
**①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。
stat中的参数意义如下:
参数 含义 D 不可中断 Uninterruptible(usually IO) R 正在运行,或在队列中的进程 S(大写) 处于休眠状态 T 停止或被追踪 Z 僵尸进程 W 进入内存交换(从内核2.6开始无效) X 死掉的进程 < 高优先级 N 低优先级 s 包含子进程 + 位于前台的进程组 l 多线种进程(如CLONE_THREAD, NPTL )
2. 进程相关命令
- 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
- 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
- kill 命令
- 使用方法
- kill 进程号
- kill -信号编号 进程号
- kill -信号宏 进程号
- 所以使用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 进程号
- 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.进程号相关函数
- getpid 获取当前进程进程号
- getppid 获取父进程号
- 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返回
- getpid 获取当前进程进程号
- getppid 获取父进程号
- 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系统编程:五)(目录操作、进程相关概念)相关推荐
- Linux系统编程.NO7——目录操作函数
5. 目录文件管理函数 5.1. 目录文件概念 目录在Linux中也是文件,也有对应的文件指针,每次读目录之前也要先打开目录,然后目录指针就出现了,第一次读就是第一个文件的信息,然后第二次读就是第二个 ...
- Linux系统编程(三)进程间的通信
Linux系统编程(三)进程间的通信 一.为什么需要进程之间的通信(IPC)? 二.管道 1.概念 2.特质 3.原理 4.局限性 5.代码 2.读入数据 三.共享存储映射 注意事项 父子进程通信 一 ...
- 【学习笔记】Linux 系统编程入门
Linux 系统编程入门 静态库与动态库 静态库命名规则 静态库的制作 静态库使用 动态库制作 动态库使用 加载动态库 静态库的优缺点 动态库的优缺点 Makefile 文件命名 工作原理 变量 模式 ...
- 【Linux | 系统编程】Linux系统编程(文件、进程线程、进程间通信)
文章目录 Linux系统编程 文件IO open/close函数 read/write函数 文件描述符 阻塞.非阻塞 fcntl函数 lseek函数 传入传出参数 文件系统 文件存储 文件操作 sta ...
- Linux系统编程-文件的操作
Linux系统编程-文件操作 前言: Linux 中所有内容都是以文件的形式保存和管理的,即一切皆文件,普通文件是文件,硬件设备(键盘.监视器.硬盘.打印机)是文件,就连套接字(socket).网络通 ...
- 初始Linux—Linux系统编程第三节——初始进程
目录 冯 · 诺依曼体系结构 操作系统:Operator System(OS) 进程的基本概念 进程标识符 通过系统调用创建进程-fork初识 进程状态 僵尸进程 孤儿进程 进程优先级 环境变量 和环 ...
- 【Linux系统编程】浅谈进程地址空间与虚拟存储空间
早期的内存分配机制 在早期的计算机中,要运行一个程序,会把这些程序全都装入内存,程序都是直接运行在内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址.当计算机同时运行多个程序时,必须保证这些 ...
- 嵌入式学习之Linux系统编程---9 目录IO之readdir函数
1.readdir函数的函数原型 #include <dirent.h> struct dirent *readdir(DIR *dirp); 对于readdir函数来说,它只有目录流指针 ...
- Linux系统编程 | 01 -文件操作
一.文件操作方法 linux中有两种方法可以操作文件:系统调用和c库函数. 1. 什么是系统调用? 由操作系统实现并提供给外部应用程序的编程接口(API),是应用程序同系统之间数据交互的桥梁. C标准 ...
- 【Linux系统编程】线程与进程的比较
在许多经典的操作系统教科书中,总是把进程定义为程序的执行实例,它并不执行什么, 只是维护应用程序所需的各种资源,而线程则是真正的执行实体. 为了让进程完成一定的工作,进程必须至少包含一个线程. 进程, ...
最新文章
- 计算机网络实验可变长子网掩码,计算机网络实验3-子网掩码与划分子网实验报告.docx...
- mysql从零开始自增id_MySQL从零开始 7-表约束之主键,自增长,唯一键
- 【程序员必看】如何用Python从0开始创建一个区块链?
- Android事件分发机制之ACTION_DOWN
- Mysql字符串截取 mysql将字符串字段转为数字排序或比大小
- 从北京回来的年轻人,我该告诉你点什么?
- Springboot整合Websocket遇到的坑_websocket session不支持序列化,无法存储至redis_Websocket相关问题总结(Session共享,用户多端登录等)
- Python风格总结:ASCII码与字符相互转换
- redis linux工具安装,linux 安装redis缓存工具
- C++判断一个序列是否为堆(最大堆、最小堆)
- 迅为iTOP-4412核心板调整电压
- IMU(陀螺仪)角速度测量原理-科氏力测旋转角速度
- 虚拟机ubuntu的联网方法(NET)
- Android布局总汇篇(XXXLayout)
- BUUCTF中的reverse2
- MCU学习——无线遥控模块
- Bean Definition到底是什么,附spring思维导图分享
- 四旋翼无人机学习第4节--STM32、MPU9250等器件的绘制
- 无准考证号的四六级查询
- HBase 数量统计
热门文章
- 经销商激励政策、策略、方案、手段、方法、措施
- 多元正态分布(Multivariate normal distribution)
- 【小程序测试】接口测试
- Ubuntu20.04 安装python3.6
- 2022年1月7日对自己近况的一次总结
- 网工日常必备思科华为设备命令对照表,全网最完整
- Ubuntu终端代理工具——proxychains
- VLAD特征(vector of locally aggregated descriptors)
- socket(四)–组播
- android仿微信发布动态功能,Android 类似微博、微信展示动态(Feed)的WeiBoLayout