Linux系统05---进程

目录

进程

1.1 进程概念

1.2 查看进程

        1.2.1 Windows 任务管理器 

        1.2.2 Linux 终端指令 

1.3 进程的特点(理解)

1.4 进程的资源分配(理解)

1.5 进程的状态(记住)

1.6 进程管理--PID

1.7 进程间关系(重点)

1.8 函数名:getpid()

1.9 函数名:getppid()

1.10 创建进程

        1.10.1 函数名:fork() (重点*****) 

        1.10.2 函数名:vfork() 

1.11 结束进程

        1.11.1 函数名:_exit() 

        1.11.2 函数名:exit() 

1.12 特殊进程:

1.13 等待进程

        1.13.1 函数名:wait() 

        1.13.2 函数名:waitpid() 

1.14 进程调用

       1.14.1 函数名:system() 

        1.14.2 exec 函数族性质 

        1.14.3 函数名:execl() 

        1.14.4 函数名:execlp() 

        1.14.5 函数名:glob() 

安装 mpg123

1. 读取目录中所有文件名 子级目录中的文件名也要显示出来 递归方法比较简单 

2. 实现 ls 主函数传参 ./a.out -l ls 只能查看可见文件 ls -a ls -l 文件类型 文件名

3. 写一个程序,实现日志保存功能,要求程序每隔 3 秒,创建一个以当前时间命名的文件,并在文件中保存一个数字,数字代表该文件是程序运行起来后的创建的第几个文件

20250402115009.log --->1

操作满足以下要求: 在目录中最多保存 10 个日志文件,如果有新的文件需要创建,则删除最老的文件,保证目录中最多只能有 10 个文件 


进程

1.1 进程概念

        代码:编程语言编写的内容 

        程序:有主函数且编译通过,生成的可执行文件(静态),硬盘中存储 

        进程:运行状态下的程序(动态),内存中运行

1.2 查看进程

        1.2.1 Windows 任务管理器 

        1.2.2 Linux 终端指令 

                ps        ps -ef         ps -aux         top 

1.3 进程的特点(理解)

        动态性:进程的实质是一次程序运行的过程,进程是动态产生动态消亡的 

        并发性:任何进程都可以和其他进程一起并发执行 

        独立性:进程是一个能独立运行的基本单位,同时也是系统分配资源和调度的基本单位 

        异步性:进程的执行具有间断性,多个进程间按照各自独立的不可预知的速度向下运行 

1.4 进程的资源分配(理解)

        系统会给每个进程开辟 4G 的虚拟内存 

                3G 用户内存+1G 的内核内存 

        堆:手动开辟 

        栈:局部变量 

        数据段:全局变量和静态变量 

                      未初始化数据段:默认值为 0 

                      初始化数据段:会初始化设置的初始值 

        文本段:常量和代码 

1.5 进程的状态(记住)

        执行态:进程正在占用 CPU(CPU 正在执行该进程) 

        就绪态:进程已经满足被 CPU 分配时间片的条件(可以被 CPU 执行),在等待 CPU 给他分配时间片 

        等待态:进程没有满足被 CPU 分配时间片的条件,需要等到条件满足 CPU 才会给它分配时间片

1.6 进程管理--PID

        一般情况下都是通过进程的 PID 号来操作进程 

1.7 进程间关系(重点)

        父子关系:进程 2 是由进程 1 创建的,那么进程 1 就是进程 2 的父进程,进程 2 就是进程 1 的子进程。 

        进程间有且只有父子关系 

1.8 函数名:getpid()

        头文件:#include <sys/types.h>

                      #include <unistd.h> 

        函数原型:pid_t getpid(void); 

        函数功能:获取进程 pid 

        函数参数:无 

        函数返回值:返回 PID 号 

        函数使用: 

1.9 函数名:getppid()

        头文件:#include <sys/types.h> 

                      #include <unistd.h> 

        函数原型:pid_t getppid(void); 

        函数功能:获取父进程 pid 

        函数参数:无 

        函数返回值:获取的 PPID 

        函数使用: 

1.10 创建进程

        方法一:直接运行可执行程序 

        方法二:在程序中去调用进程创建函数去创建进程--fork、vfork。 

        1.10.1 函数名:fork() (重点*****) 

                子进程复制父进程资源,然后和父进程从同一位置向下运行,执行的先后关系不确定 

                头文件:#include <sys/types.h>

                              #include <unistd.h> 

                函数原型:pid_t fork(void); 

                函数功能:创建子进程 

                函数参数:无 

                函数返回值:-1 代表子进程创建失败,0 代表子进程,大于 0 代表父进程 

                函数使用: 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <glob.h>
int Print(void);
int main()
{
	int a = 0;
	glob_t gl = {0};
	pid_t pid = fork();
	if(pid==0)
	{
		a+=5;
		printf("B:a=%d\n",a); // 5
		exit(0);
	}
	else if(pid>0)
	{
		printf("A:a=%d\n",a); // 0
	}
	return 0;
} 

        1.10.2 函数名:vfork() 

                子进程占用父进程资源,然后子进程先使用资源执行,子进程结束后,父进程才能使用资源 

                头文件:#include <sys/types.h> 

                              #include <unistd.h> 

                函数原型:pid_t vfork(void); 

                函数功能:创建子进程,返回子进程 PID 

                函数参数:无 

                函数返回值:父进程返回子进程 PID 子进程返回 0 

                函数使用:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <glob.h>
int Print(void);
int main()
{
	int a = 0;
	glob_t gl = {0};
	pid_t pid = vfork();
	if(pid==0)
	{
		a+=5;
		printf("B:a=%d\n",a); // 5
		exit(0);
	}
	else if(pid>0)
	{
		printf("A:a=%d\n",a); //5
	}
	return 0;
} 

1.11 结束进程

        方法一:外部信号 

                在终端 ctrl+c 可以结束进程 

                在终端输入:kill -9 PID 可以结束进程 

                ps -ef | grep "./a.out" 

        方法二:内部程序 

                1. main()中调用 return 

                2. 进程退出函数--- exit()、_exit() 

        1.11.1 函数名:_exit() 

                头文件:#include <unistd.h> 

                函数原型:void _exit(int status); 

                函数功能:退出进程,不清空缓冲区 

                函数参数:获取进程退出时的状态 一般填 0 

                函数返回值:无 

                函数使用: _exit(0);

        1.11.2 函数名:exit() 

        头文件:#include <stdlib.h> 

        函数原型:void exit(int status); 

        函数功能:退出进程,清空缓冲区 

        函数参数:获取进程退出时的状态 一般填 0 

        函数返回值:无 

        函数使用: exit(0);

1.12 特殊进程:

        了解: 

                0 号进程:操作系统启动的引导程序 祖先进程 

                1 号进程:操作系统启动的第一个程序 

        掌握: 

                孤儿进程: 父进程死了,子进程还在运行。孤儿进程会被系统中设置好的一个进程收养,并且等孤儿进程死了之后给它收尸

                僵尸进程: 子进程死了,父进程没有给自己去收尸。这个时候子进程就会变成一个僵尸进程,僵尸进程所占用的资源基本上会被完全释放,除了它所占用的进程号。父进程在退出之前,一定会给所有的僵尸进程收 尸。但是有些工程中的父进程需要长时间不停机运行,会导致僵尸进程的资源无法得到及时的回收处理。所以咱们在编写代码的过程中,一定要尽量避免僵尸进程的产生。

                可以通过在父进程中调用,下面的进程的等待函数来避免僵尸进程的产生。

1.13 等待进程

        1.13.1 函数名:wait() 

                头文件:#include <sys/types.h>

                              #include <sys/wait.h> 

                函数原型:pid_t wait(int *wstatus); 

                函数功能:阻塞,等待任意子进程结束 

                函数参数:进程结束状态 一般填 NULL 

                函数返回值:返回结束的子进程 pid 

                函数使用: 

        1.13.2 函数名:waitpid() 

                头文件:#include <sys/types.h> 

                               #include <sys/wait.h> 

                函数原型:pid_t waitpid(pid_t pid, int *wstatus, int options); 

                函数功能:等待,子进程结束

                函数参数: 

                        pid: 

                                负数:进程组号(进程的 PID 的绝对值) 

                                0:当前进程组中任意子进程 

                                正数:指定的进程号 PID 

                                <0 任意子进程 

                                 0 进程组中的任意子进程

                                 >0 等待的子进程 pid 

                        wstatus:保存子进程的退出状态,一般填 NULL 

                        options: 

                                WNOHANG:非阻塞,等待子进程结束 

                                0:阻塞,等待子进程结束 

                函数返回值:返回结束的子进程 pid,非阻塞情况下子进程未结束返回-1 

                函数使用: wait(NULL) == waitpid(0,NULL,0); 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int Print(void);
int main()
{
	int a = 0;
	pid_t pid = fork();
	if(pid==0)
	{
		printf("B:%d\n",getpid());
		printf("B:A:%d\n",getppid());
		a+=5;
		printf("B:a=%d\n",a);
	}
	else if(pid>0)
	{
		//wait(NULL);
		//waitpid(0,NULL,0);
		//waitpid(pid,NULL,0);
		waitpid(pid,NULL,WNOHANG);
		printf("A:a=%d\n",a);
		Print();
		printf("A end!!!\n");
	}
	return 0;
}
int Print(void)
{
	printf("A:%d\n",getpid());
	//_exit(0);
	exit(0);
	return 0;
} 

1.14 进程调用

       1.14.1 函数名:system() 

                头文件:#include <stdlib.h> 

                函数原型:int system(const char *command); 

                函数功能:在一个进程中调用系统指令 

                函数参数:系统指令的字符串形式 “clear” 

                函数返回值:成功返回 0,失败返回-1 

                函数使用: 

        1.14.2 exec 函数族性质 

                system()执行完成之后,会继续执行进程剩余内容 

                exec 函数族在原进程中调用另一个进程执行指令 

                执行完成之后,不会继续执行原进程剩余内容 

                int execl(const char *pathname, const char *arg, ... * (char *) NULL */);

                int execlp(const char *file, const char *arg, ... * (char *) NULL */);

                int execle(const char *pathname, const char *arg, ... *, (char *) NULL, char *const envp[] */);

                int execv(const char *pathname, char *const argv[]); 

                int execvp(const char *file, char *const argv[]); 

                int execvpe(const char *file, char *const argv[],char *const envp[]); 

        1.14.3 函数名:execl() 

                头文件:#include <unistd.h> 

                函数原型:int execl(const char *pathname, const char *arg, ... * (char *) NULL */);

                函数功能:调用进程 

                函数参数: 

                        const char *pathname:路径+可执行程序 

                        const char *arg, ...:指令,其他参数 

                函数返回值:错误返回-1,错误码

                函数使用: 

        1.14.4 函数名:execlp() 

                头文件:#include <unistd.h> 

                函数原型:int execlp(const char *file, const char *arg, ... * (char *) NULL */);

                函数功能:调用进程 

                函数参数: 

                        const char * file:可执行程序 

                        const char *arg, ...:指令,其他参数 

                函数返回值:错误返回-1,错误码 

                函数使用: 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <glob.h>
int Print(void);
int main()
{
	int a = 0;
	pid_t pid = vfork();
	if(pid==0)
	{
		system("clear");
		//execl("/usr/bin/ls","ls","-a",NULL);
		//execlp("ls","ls","-a",NULL);
		execlp("ls","ls","./log","-a",NULL);
		printf("B:end!!!\n");
		exit(0);
	}
	else if(pid>0)
	{
		//wait(NULL);
		system("ls -a");
	}
	return 0;
}

        1.14.5 函数名:glob() 

        头文件:#include <glob.h> 

        函数原型:int glob(const char *pattern, 

                          int flags, 

                          int (*errfunc) (const char *epath, int eerrno),

                          glob_t *pglob); 

        函数功能:在指定路径下查找指定格式的文件并保存信息 

        函数参数: 

                        const char *pattern:文件格式 “./*.mp3” 

                        int flags:0 

                        int (*errfunc) (const char *epath, int eerrno):NULL 

                        glob_t *pglob:保存信息的结构体地址 

        函数返回值:成功返回 0 

        函数使用: 

安装 mpg123

sudo apt-get install mpg123

使用:        mpg123 歌曲名 

退出:        q 

测试并分析代码执行结果为什么是这样

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <glob.h>
int main()
{
	fork();
	fork();
	fork();
	printf("hello\n");
	return 0;
} 

1. 读取目录中所有文件名 子级目录中的文件名也要显示出来 递归方法比较简单 

#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
//1. 读取目录中所有文件名 子级目录中的文件名也要显示出来 递归方法比较简单
void fun(char *path);

int main(int argc, int *argv[])
{
	fun(argv[1]);
	return 0;
}

void fun(char *path)
{
	DIR *dirp = NULL;
	dirp = opendir(path);
	struct dirent *dent = NULL;
	while(dent = readdir(dirp))
	{
		if((!strcmp(".",dent->d_name)) ||(!strcmp("..",dent->d_name)))
		{
			continue;
		}
		if(dent->d_type == 8)
		{
			char *p = dent->d_name;
			p += strlen(dent->d_name)-2;
			if(strcmp(".c", p) == 0)
			{
				printf("%s\n", dent->d_name);
			}
		}
		else if(dent->d_type == 4)
		{
			chdir(path);
			fun(dent->d_name);
			chdir("..");
		}
	}
	
}

2. 实现 ls 主函数传参 ./a.out -l ls 只能查看可见文件 ls -a ls -l 文件类型 文件名

#include <sys/types.h>
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
// 0000 ls
// 0001 ls -a
// 0010 ls -l
// 0011 ls -al
//2. 实现 ls 主函数传参 ./a.out -l ls 只能查看可见文件 ls -a ls -l 文件类型 文件名
void fun(char *path, unsigned char flag);
unsigned char flag = 0;
int main(int argc, char *argv[])
{
	char *path = ".";
	for(int i = 1, j = 0; i < argc; i++)
	{
		if(argv[i][j] == '-')
		{
			while(argv[i][j + 1])
			{
				if(argv[i][j + 1] == 'a')
				{
					flag |= 0x01 << 0;
				}
				else if(argv[i][j + 1] == 'l')
				{
					flag |= 0x01 << 1;
				}
				j++;
			}
		}
		else if(argv[i] != NULL)
		{
			path = argv[i];
			printf("%s\n",argv[i]);
		}
	
	}
	fun(path, flag);
	return 0;
}

void fun(char *path, unsigned char flag)
{
	DIR *dirp = opendir(path);
	struct dirent *dent = NULL;
	while(dent = readdir(dirp))
	{
		if((flag == 0x00) && dent->d_name[0] != '.')
		{
			printf("%s\t", dent->d_name);
		}
		else if(flag == 0x01)
		{
			printf("%s\t", dent->d_name);
		}
	}
	printf("\n");
}

3. 写一个程序,实现日志保存功能,要求程序每隔 3 秒,创建一个以当前时间命名的文件,并在文件中保存一个数字,数字代表该文件是程序运行起来后的创建的第几个文件

20250402115009.log --->1

操作满足以下要求: 在目录中最多保存 10 个日志文件,如果有新的文件需要创建,则删除最老的文件,保证目录中最多只能有 10 个文件 

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <glob.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int n = 1;
void gettime(char * buf);
int log_remove(void);
int log_creat(void);

int main()
{
	int s = 0;
	while(1)
	{
		if(s % 3 == 0)
		{
			log_remove();
			log_creat();
		}
		s++;
		sleep(1);//非阻塞
	}
	return 0;
}

int log_creat(void)
{
	char filename[50] = {0};
	gettime(filename);
	int fd = open(filename, O_CREAT|O_WRONLY,0664);
	if(fd == -1)
	{
		perror("open");
		return -1;
	}
	char data[10] = {0};
	sprintf(data, "%d", n);
	write(fd, data, strlen(data));
	close(fd);
	n++;
	return 0;
}

void gettime(char *buf)
{
	time_t tm = time(0);
	struct tm *lm = localtime(&tm);
	sprintf(buf,"%04d%02d%02d%02d%02d%02d.log",lm->tm_year+1900,lm->tm_mon+1,lm->tm_mday,lm->tm_hour,lm->tm_min,lm->tm_sec);
}

int log_remove(void)
{
	glob_t gl = {0};
	glob("*.log", 0, NULL, &gl);
	if(gl.gl_pathc >= 10)
	{
		char *p = gl.gl_pathv[0];
		for(int i; i < gl.gl_pathc; i++)
		{
			if(strcmp(p,gl.gl_pathv[i]) > 0)
			{
				p = gl.gl_pathv[i];
			}
		}
		remove(p);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力做小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值