Linux系统——进程与线程

一、回收资源空间

pid_t wait(int *wstatus);

       功能:阻塞父进程 ,等待回收子进程的资源空间
       参数:
               wstatus :保存子进程消亡状态的变量地址
                                 NULL:不保存子进程退出的状态
       返回值:
            成功:返回回收到的子进程的PID号
            失败:-1

【wait(NULL)】

    pid_t waitpid(pid_t pid, int *status, int options);
    
    功能:回收指定进程的资源
        和wait功能相似,比wait更灵活
    参数:
    pid:
        <-1 回收指定进程组内的任意子进程 (-100.等待GID=100的进程组中的任意子进程)
        -1 回收任意子进程,组内外
        0 回收和当前调用waitpid一个组的所有子进程,组内 
        > 0 回收指定ID的子进程
    
     status 子进程退出时候的状态,
              如果不关注退出状态用NULL;
     options 选项:
              0  表示回收过程会阻塞等待
            WNOHANG 表示非阻塞模式回收资源。
    返回值: 成功 返回接收资源的子进程pid
            失败  -1
            设定为非阻塞且没有回收到子进程返回0 

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>

int main(int argc, const char *argv[])
{
	pid_t pid = fork();
	if (pid > 0)
	{
		while (1)
		{
			int wstatus;
			//pid_t pidtmp = waitpid(-1, &wstatus, 0);  ==>wait(&wstatus)
			pid_t pidtmp = waitpid(-1, &wstatus, WNOHANG);
			printf("pidtmp = %d\n", pidtmp);
			if (0 != pidtmp)
			{
				if (WIFEXITED(wstatus))
				{
					printf("%d over normall, state : %d\n", pidtmp, WEXITSTATUS(wstatus));
				}
				else if (WIFSIGNALED(wstatus))
				{
					printf("%d ober by signal,signal num = %d\n", pidtmp, WTERMSIG(wstatus));
				}
			}

			printf("I am father : pid= %d\n", getpid());
			sleep(1);
		}
	
		
	}
	else if (0 == pid)
	{
		int i = 20;
		while (i--)
		{
			printf("I am son : pid = %d\n", getpid());
			sleep(1);
		}

		exit(9);
		//return 9;
	}
	else
	{
		perror("fork error");
	}
	return 0;

二、子进程资源回收策略

1. wait阻塞回收:一般情况下,父进程专门负责资源回收;
2. waitpid非阻塞方式回收:搭配轮询方式回收。
3. 不回收:子进程的任务需要一直执行
4. 异步回收:当子进程结束时通知父进程进行回收

三、exec函数族

       在一个进程里面执行另外一个文件(可执行文件):
       本质:将文本去的指令代码替换成exec要执行的文件的指令。
       int execl(const char *path, const char *arg, ...
                       /* (char  *) NULL */);
       参数:
               path:要执行的可执行文件的路径和名称
               arg:执行该可执行文件时需要传递的参数
              NULL :参数传递结束标志
       返回值:
            出错:-1
       int execlp(const char *file, const char *arg, ...
                       /* (char  *) NULL */);
       功能:从PATH指定的系统路径下寻找该可执行文件
       参数:
                file:需要执行的可执行文件的名称(系统路径下已有的文件)
               arg : 执行该可执行文件时需要传递的参数
       int execle(const char *path, const char *arg, ...
                       /*, (char *) NULL, char * const envp[] */);
       int execv(const char *path, char *const argv[]);
       int execvp(const char *file, char *const argv[]);
       int execvpe(const char *file, char *const argv[],
                       char *const envp[]);

l:list  列表
p:path  路径 : 系统路径
v:vector 容器
e:env  环境变量

在同一目录下,创建一个hello.c文件,在其编写打印出“hello world”字符串的代码,运行后生成可执行文件hello

创建exec.c文件,使运行exec.c文件而执行hello.c

int main(int argc, const char *argv[])
{


	printf("exec : pid = %d\n", getpid());

	execl("./hello", "./hello", NULL);
	
	printf("after exec\n");


	return 0;
}

注:使用exec函数,他不会在自己的 .c 中结束,而是在hello.c中结束,也就是在子进程中结束,再就是说  printf("after exec\n");

这行代码并不会执行,如过要返回父进程中结束,需要用下面介绍的函数。

四、system函数

int main(int argc, const char *argv[])
{
	printf("system : pid = %d\n", getpid());
    
    system("./hello");
	
	printf("After system\n");

	return 0;
}

其参数,是需要执行其他可执行文件的地址

手撕system函数

int my_system(char *buff)
{
	char *arg[10] = {NULL};
	int i = 0;
	char cmd[512] = {0};

	strcpy(cmd, buff);

	arg[i] = strtok(cmd, " ");
	while (arg[i] != NULL)
	{
		printf("arg[%d] = %s\n", i, arg[i]);
		i++;
		arg[i] = strtok(NULL, " ");
	}


	pid_t pid = fork();
	if (pid > 0)
	{
		wait(NULL);
	}
	else if (0 == pid)
	{
		execvp(arg[0], arg);

	}

	return 0;
	
}

int main(int argc, const char *argv[])
{
	printf("system : pid = %d\n", getpid());
//	system("./hello");
	
	my_system("ls -l");

	
	printf("After system\n");

	return 0;
}

(srctok函数在之前文章有介绍,需要自行搜索)

五、线程

1. 什么是线程

轻量级的进程,可实现多任务的并发。
进程是操作系统资源分配的最小单位;
线程是操作系统任务调度的最小单位。

2. 线程的创建

线程由某个进程创建。
进程创建线程时,会为其分配独立的(8M)栈区空间;
线程和所在进程,以及进程中的其他线程,共用进程的堆区、数据区、文本区。

3. 线程的调度

宏观并行,微观串行     

4. 线程消亡

  1.  线程退出
  2. 回收线程资源空间

5. 进程和线程的区别


     进程:进程是操作系统资源分配的最小单位;
     资源消耗:进程资源开销大,每次创建都需要有0-4G的虚拟内存空间   
     效率角度:由操作系统创建,创建时耗时比线程大;跨进程调度比跨线程调度慢;
     通信方面: 进程间不能直接通信,需要使用进程间通信机制(IPC机制)
     安全性角度:进程安全性比线程高,各进程空间独立

     

     线程:线程是操作系统任务调度的最小单位。
     资源消耗:资源开销较小,只需要所在进程为其开辟8M的栈区空间
     效率角度:由所在进程创建;跨进程调度比跨线程调度慢;
     通信方面:通信简单,可以使用线程共享的区域进行通信(比如全局变量)
     安全性角度:线程没有进程安全性好,一个线程异常可能影响同一进程中的所有线程

6.线程的相关编程

     1. 线程的创建: pthread_create()
                                pthread_self():获取当前线程的ID号
     2. 线程调度:由操作系统调度
     3. 线程消亡: 
           1. 线程退出:pthread_exit();
           2. 线程回收:pthread_join();

       #include <pthread.h>

(注:线程函数库是由Linux系统向RedHat公司引入,并不属于Linux,也就是在编译时,需要加上  - pthread/-lpthread)

       int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
      功能:创建一个新的线程
      参数:
              thread : 保存线程ID的变量地址
              attr:线程属性的对象地址
                       NULL : 按照默认属性创建
             start_routine:函数的指针:指向线程启动后要执行的任务(线程任务函数)
             arg:为线程任务函数传递的参数
     返回值:
            成功:0
            失败:非0

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>

//次线程
void *task(void *arg)
{
	printf("I am thread : tid = %ld\n", pthread_self());
}


int main(int argc, const char *argv[])
{
	//主进程、主线程
	pthread_t tid;

	int ret = pthread_create(&tid, NULL, task, NULL);
	if (ret !=0)
	{
		printf("pthread_create error\n");
		return -1;
	}
	
	while (1)
	{}

	return 0;

代码运行速度较快,可能导致task函数没有执行,就导致运行结束,所以加个死循环,手动停止,或者将其更改为

sleep(2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值