exec函数族 和 线程 学习

一.exec函数族

    extern char **environ;

    int execl(const char *path, const char *arg, ...    (后面跟的参数)
                    /* (char  *) NULL */);

eg:

int main(void)                  //execl用法
{
	printf("======================");
	execl("./hello","./hello","艳阳","高照",NULL);       //后面跟的“传参”的参数,优先在当前目录来找

	return 0;
}


    int execlp(const char *file, const char *arg, ...   (区别l在于在哪个目录下寻找需要执行的文件)
                    /* (char  *) NULL */);

eg:

extern char **environ;            //execlp的用法
int main(void)
{
	int i = 0;
	char tmpbuff[1024] = {0};
	printf("===================/n");
	for (i = 0; environ[i] != NULL; i++)
	{
		printf("environ[%d] = %s\n", i, environ[i]);      //打印程序运行时的隐藏运行文件
	}

	printf("===================\n");
	printf("PATH:%s\n",getenv("PATH"));   //获取PATH中的路径,此时是未改变的路径,是优先在系统下寻找
	printf("===================\n");
	getcwd(tmpbuff,sizeof(tmpbuff));       //获取当前路径
	setenv("PATH",tmpbuff,1);             //将原本为改变的路径更改为获取的当前路径经,代表在当下路径寻找文件
	printf("PATH:%s\n",getenv("PATH"));   //验证更改后的路径
	printf("===================\n");

	execlp("hello","hello","艳阳","高照",NULL);
	return 0;
}


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

eg:

int main(void)                  //execv用法
{
	char *ch[10] = {"./hello","艳阳","高照",NULL};
	printf("======================");
	execv("./hello",ch);       //后面跟的指针数组首地址,优先在当前目录寻找

	return 0;
}


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

eg:

int MySystem(const char *pcommand)           //函数,实现调用ls功能
{
	char commandbuf[1024] = {0};
	char *parg[10] = {NULL};
	int cnt = 0;
	pid_t pid;

	strcpy(commandbuf,pcommand);             //pcommand是一个常量,要变量才能使用strtok,所以将它放在数组中

	parg[cnt] = strtok(commandbuf," ");     //第一次分割字符串放在parg【0】中
	cnt++;

	while((parg[cnt] = strtok(NULL," "))!=NULL)  //后续分割,当返回值为NULL代表识别不到,停止
	{
		cnt++;
	}

	pid = fork();                //建立子程序用来执行execvp,以防父程序用完execvp后程序结束,无法执行后面的
	if(pid == -1)
	{
		perror("fail to fork");
		return -1;
	}
	if(pid == 0)
	{
		execvp(parg[0],parg);   //parg[0]是一个ls功能,在bin中储存,parg是一个指针数组,存放的指令
	}
	wait(NULL);  //回收子进程空间

	return 0;
}

int main(void)
{
	printf("shang\n");      //测试主程序运行
	MySystem("ls -l");      //调用函数
	printf("xia\n");        //测试主程序运行

	return 0;

}


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

    功能:
        利用进程空间执行另外一份代码
    
    l:参数以列表形式传递
    v:参数以指针数组形式传递
    e:更新环境变量
    p:在系统指定目录下查找文件

    getenv
    char *getenv(const char *name);
    功能:
        获得环境变量名对应的值
    
    setenv
    int setenv(const char *name, const char *value, int overwrite);
    功能:
        设置环境变量的值
    参数:
        name:环境变量名
        value:环境变量的值
        overwrite:非0 覆盖
                  0   不覆盖
    返回值:
        成功返回0 
        失败返回-1 

二.线程

1.概念:

线程是一个轻量级的进程,位于一个进程空间的内部,一个进程可以创建多个线程

2.线程的创建:

线程独占 栈空间,文本段,数据段和堆区与进程程序

3.线程调度:

与进程调度是一样的,宏观并行,围观穿行

4.线程的消亡:

与进程消亡是一样的

5.进程和线程的区别:

                                   进程是操作系统资源分配的最小单元
                                   线程是CUP任务调度的最小单元
                                   多个线程的任务调度的时候比进程更加节省资源空间

6.多进程多线程的优缺点:

               从效率来说:多线程 > 多线程  ---   多线程只需要在同一进程空间切换,多进程需要在不同的空间切换
              通信:多线程 > 多进程 --- 线程共享全局变量,可以通过全局变量实现数据通信  ; 
进程空间是独立的,没有共享空间,通信实现比较复杂
               通信实现:多进程 > 多线程 --- 线程共享空间操作时引发资源竞争  ;  进程没有共享空间,不存在资源竞争的问题
              安全:多进程 > 多线程 --- 一个进程异常不会影响到其余空间 ; 一个线程异常结束会导致进程进程异常结束 , 进程异常结束 , 该进程内所有线程所有线程任务均无法向下执行。

7.线程相关的函数接口:

创建: pthread_create 
退出: pthread_exit 
回收: pthread_join 

        1.pthread_create

         int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                          void *(*start_routine) (void *), void *arg);
          功能:
            在该进程中创建一个新的线程
          参数:
            thread:存放线程ID空间首地址
            attr:线程属性空间首地址
            start_routine:线程要执行的函数的入口
            arg:给线程函数的参数
          返回值:
            成功返回0 
            失败返回错误码

        编译时加 -lpthread选项

         2.pthread_self

          pthread_t pthread_self(void);
          功能:
            获得调用该函数线程的ID  

练习:创建三个线程任务,线程打印 线程(TID:XXXX)开始执行------------------------------------------------

void *threadfun1(void *arg)              //线程执行的函数入口1
{
	printf("线程1(TID:%#x)开始运行!\n",(unsigned int)pthread_self());

	return NULL;

}
void *threadfun2(void *arg)              //线程执行的函数入口2
{
	printf("线程2(TID:%#x)开始运行!\n",(unsigned int)pthread_self());

	return NULL;

}
void *threadfun3(void *arg)              //线程执行的函数入口3
{
	printf("线程3(TID:%#X)开始运行!\n",(unsigned int)pthread_self());

	return NULL;

}

int main(void)
{
	int ret = 0;
	int i = 0;
	pthread_t tid[3];
	void *(*th[10])(void *) = {threadfun1,threadfun2,threadfun3};  //函数指针数组

	for(i=0;i<3;i++)
	{
		ret = pthread_create(&tid[i],NULL,th[i],NULL);

		if(ret != 0)
		{
			perror("fail to pthread_create");
			return -1;
		}
	}

	while(1)
	{

	}

	return 0;

}

          3.pthread_exit 

          void pthread_exit(void *retval);
          功能:
            让调用该函数的线程任务结束
          参数:
            retval:线程结束的值
        

          4.pthread_join 

          int pthread_join(pthread_t thread, void **retval);
          功能:
            回收线程空间
          参数:
            thread:线程的ID号
            retval:存放线程结束状态空间的首地址
          返回值:
            成功返回0 
            失败返回错误码

eg:pthread_exit,pthread_join 用法示例

void *thread(void *arg)
{
	printf("线程(TID: %#x)开始运行\n",(unsigned int)pthread_self());
	sleep(3);
	printf("线程即将结束\n");
	pthread_exit("Game Over!");          //线程任务的结束

	return NULL;
}

int main(void)
{
	pthread_t tid;
	void *arg = NULL;

	pthread_create(&tid,NULL,thread,NULL);  //线程任务的开始

	pthread_join(tid,&arg);           //1参数:线程的ID号,2参数:存放线程结束状态空间的首地址
	printf("arg = %s\n",(char *)arg);

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值