Day 29 守护线程, minishell_execl, 使用子线程传参修改变量。

一、守护进程程序编写框架 ==》5 步骤

1、创建孤儿进程 ==》fork 父进程退出,子进程保留

fork()
exit() ===>父进程

2、创建会话组组长 ===>独立session

	setsid()===>   pid_t setsid(void);

功能:将当前进程脱离终端控制变为会话组组长权限。
参数:无
返回值:成功 返回当前会话组组长pid
		失败  -1;
  /home/linux/123/

3、修改工作目录 ===》不被卸载

chdir("/");
chdir() ===int chdir(const char *path);
功能:修改当前工作进程的工作目录。
参数:path 要修改到的目的工作目录。
返回值:成功 0
		失败 -1;

4、修改权限掩码 ===》 提权
umask(0)
#include <sys/types.h>
#include <sys/stat.h>

mode_t umask(mode_t mask);
功能:修改当前环境下的文件权限掩码
参数:mask 要修改的目标掩码,在守护进程
	  中该值为 0,表示目标权限全部放开。
返回值:成功  修改之后的文件权限掩码
	   失败 -1;

5、关闭文件描述符===>清理文件 0 1 2
close() ==》getdtablesize() 1024
int getdtablesize(void);
功能:0

参数:无
返回值:成功 最大描述符
		失败 -1;

6、验证是否是一个守护进程

6.1  ps aux  ==>STAT 列 ===》会话组长 Ss
6.2  ps aux  ==>TTY  列 =?  ==》表示没有终端关联
6.3  ps -ef  ==>ppid =1 ===>孤儿进程
ps -eo pid,ppid,stat,tty,comm
必须满足以上三个要求,则为守护进程.

如果要关闭守护进程则需要使用命令 kill +pid 或 kill -9 +pid


#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, const char *argv[])
{
pid_t pid;
pid =fork();
if(pid > 1)
{
	printf("%d\n", pid);
	exit(1);
}

if(0 == pid)
{
	setsid();
	chdir("/");
	umask(0);
	int i;
	for(i = 0; i < 1024; ++i)
		close(i);

	while(1)
	{
		printf("++++++++++++");
		sleep(1);
	}
}
if(pid < 0)
{
	exit(1);
}
return 0;

}



用进程的方式,打开程序来完成minishell

此版本要自己写许多选择有些low

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char path[256];
	char cmd[256] = {0};
	while(1)
	{
		char *arg[4] = {NULL};
		while(1)
		{
		getcwd(path, 256);
		printf("linux/@ubuntu %s$", path);
		fgets(cmd, 256, stdin);
		cmd[strlen(cmd)-1] = '\0';
		if( strlen(cmd) !=0)
		break;
		}
		arg[0] = strtok(cmd, " ");
		arg[1] = strtok(NULL, " ");
		arg[2] = strtok(NULL, " ");
		arg[3] = strtok(NULL, " ");
		if(0 == strcmp(arg[0], "quit"))
		{
			break;
		}
		pid_t pid = fork();
		if(pid > 0)
		{
			printf("%d\n", pid);
			wait(NULL);     //等待回收子进程
		}

	if(0 == pid)
	{
		if(0 == strcmp(arg[0], "ls"))
		{
			//int execlp(const char *file, const char *arg, ...);    execl()函数为最初的。 此处的execlp(); 包含了环境变量。
			execlp("ls", "ls", arg[1], arg[2], arg[3], NULL);
			exit(1);
		}

		if(0 == strcmp(arg[0], "cp"))
		{
			//int execlp(const char *file, const char *arg, ...);
			execlp("cp", "cp", arg[1], arg[2], arg[3], NULL);
			exit(1);
		}


		if(0 == strcmp(arg[0], "cat"))
		{
			//int execlp(const char *file, const char *arg, ...);
			execlp("cat", "cat", arg[1], arg[2], arg[3], NULL);
			exit(1);
		}
	}


	if(pid < 0)
	{
		exit(1);
	}


}
return 0;

}


此为Plus 版本
将命令写到一个数组中

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    char path[256];
	char cmd[256] = {0};
	while(1)
	{
		char *arg[10] = {NULL};
		while(1)
		{
		getcwd(path, 256);
		printf("linux/@ubuntu %s$", path);
		fgets(cmd, 256, stdin);
		cmd[strlen(cmd)-1] = '\0';
		if( strlen(cmd) !=0)
		break;
		}
		arg[0] = strtok(cmd, " ");
		int i;
		for(i = 1; i < 10; ++i )
		{
			arg[i] = strtok(NULL, " ");
		}
		
		if(0 == strcmp(arg[0], "quit"))
		{
			break;
		}
	
	if(0 == strcmp(arg[0],"cd"))  //此处可以切换路径
	{
		chdir(arg[1]);
		continue; // 跳出本单次循环可以回到前面重新执行。
	}
	pid_t pid = fork();
	if(pid > 0)
	{
		printf("%d\n", pid);
		wait(NULL);   //此处等待子进程回收。
	}

	if(0 == pid)
	{
		//int execvp(const char *file, char *const argv[]);  此处execlvp() 包含了环境变量,还包含了数组矢量 vector 。
		execvp(arg[0], arg);
		exit(1);
	}


	if(pid < 0)
	{
		exit(1);
	}


}
return 0;

}



创建子线程,在主线程中开辟结构体空间,在子线程中写入内容,然后子线程退出,主线程回收子线程参数。最后在主线程中读出写入结构体中的值。
方法一:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

typedef struct student 
{
	char name[100];
	char age[50];
	char addr[100];
}Per;

void *th(void * arg)
{
	printf("the second thread_id is %lu\n", pthread_self());
	Per *p = (Per *)arg;
	printf("please input name:\n");
	scanf("%s", p->name);

	printf("please input age:\n");
	scanf("%s", p->age);

	printf("please input addr:\n");
	scanf("%s", p->addr);
	printf("recieve over!\n");

	pthread_exit(p);
}
int main(int argc, const char *argv[])
{   
	Per per;

Per *temp;

temp = &per;

pthread_t tid;
pthread_create(&tid, NULL, th, temp);

void *ret;
printf("the main thread_id is %lu\n", pthread_self());
pthread_join(tid, &ret);
printf("name: %s  age: %s  addr:%s \n", ((Per *)ret)->name, ((Per *)ret)->age, ((Per *)ret)->addr);
	return 0;
}

方法二;
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>

typedef struct student 
{
	char name[100];
	char age[50];
	char addr[100];
}Per;

void *th(void * arg)
{
	printf("the second thread_id is %lu\n", pthread_self());
	Per *p = (Per *)arg;
	printf("please input name:\n");	
	fgets(p->name, 100, stdin);

printf("please input age:\n");
fgets(p->age, 100, stdin);

printf("please input addr:\n");
fgets(p->addr, 100, stdin);
printf("recieve over!\n");

pthread_exit(p);

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

Per *temp;
temp = malloc(sizeof(Per));

pthread_t tid;
pthread_create(&tid, NULL, th, temp);

void *ret;
printf("the main thread_id is %lu\n", pthread_self());
pthread_join(tid, &ret);
Per *p = (Per *)ret;
puts(p->name);
puts(p->age);
puts(p->addr);
free(temp);
return 0;

}

用scanf() 和fgets(); 接收时有些区别。 前者遇见空格及回车都会认为输入结束,因此不能用前者输入带空格的字符。 后者则可以接收空格。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值