linux系统调用线程

1. 基础概念

早期unix系统中,没有线程概念,后来才引入线程
 linxu 为了迎合 windows引入了线程
 gdb不支持线程,因为gdb比线程出现了早
 区别:
 线程: 有独立的pcb.  没有独立的进程地址空间,线程在进程内部,共享进程地址空间
 进程: 有独立的进程 地址空间,有独立的pcb
 线程是分配资源的最小单位,如何理解: *  如果一个进程A有3个线程,那么cpu会把A进程当作4个进程,cpu分配时间片个A进程    给优先
 是不是线程越多进程优先级越高: 但线程数量达到一定程度的时候,优先级会降低
  进程是分配资源的最小单位:

  本章总结 线程进程函数总结对比
  *    pthread_create()   fork()
  *    pthread_self()     getpid()
  *    pthread_exit()     exit()
  *    pthread_join()     wait/waitpid
  *    pthread_cancle()   kill
  *    pthread_detach()

 2. 线程函数 

   2.1.pthread_create

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <pthread.h>
#include <errno.h>
#include <string.h>


void* tfun(void* args){
	int* j=(int *)args;
	printf("son thread.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),*j);
   // printf("---%d---",*j);
	return NULL;
}
int main0000014(){
    /**
     *  线程共享资源:
     *  1. 文件描述符表
     *  2. 当前工作目录
     *  3. 用户ID 和组 ID
     *  4. 内存地址空间(.text/.data/.bss/堆/共享库)[共享全局变量]
     *  非共享:
     *1. 线程id
     *2. 栈
     *  优点: 效率高
     */

	// lwp 标识线程身份,cpu调度区分   线程id:  进程内部不同线程区分
	pthread_t tid;
	// 线程id,线程属性,回调函数,回调函数参数
	// 打印主线程
	printf("main thread..pid = %d ... pthread %lu \n",getpid(),pthread_self());
    int j=1000;
	int ret = pthread_create(&tid,NULL,tfun,&j);  // 返回线程id
	sleep(1);
	if(ret == -1){
		perror("pthread_create fail");
		exit(-1);
	}
	// gcc single.c -o single.o -lpthread

	return 0;
}

   2.1.1线程传递问题

void* tfun(void* args){
	int* j=(int *)args;
	printf("son thread.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),*j);
   // printf("---%d---",*j);
	return NULL;
}

/**
 * 循环创建多个线程
 */
int main0000015() {
	pthread_t tid;
	int ret=0;
	for (int i = 0; i < 10; i++) {
		// 错误
		/**
		 * son thread.... pid = 3521 ...  140422606616320-args--2
son thread.... pid = 3521 ...  140422589830912-args--5
son thread.... pid = 3521 ...  140422598223616-args--3
son thread.... pid = 3521 ...  140422615009024-args--1
son thread.... pid = 3521 ...  140422581438208-args--7
son thread.... pid = 3521 ...  140422564652800-args--7
son thread.... pid = 3521 ...  140422573045504-args--7
son thread.... pid = 3521 ...  140422556260096-args--8
son thread.... pid = 3521 ...  140422479345408-args--9
son thread.... pid = 3521 ...  140422470952704-args--10
 出现重复数据,
 为什么: for循环不断执行当,但i=5的时候在栈中,子线程回调才第一次执行,才切换成内核态取出i=5,实际的需要的是0
 解决方法: 直接传递值
		 */
		ret= pthread_create(&tid, NULL, tfun, (void*) &i);  // 返回线程id
		if (ret !=0 ) {
			perror("pthread_create fail");
			exit(-1);
		}
	}
	sleep(1);
	return 0;
}

   2.2.pthread_self

void* tfun1(void* args){
	int j=(int )args;
	printf("son thread...tfun1.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),j);
   // printf("---%d---",*j);
	return NULL;
}
int main0000016() {
	pthread_t tid;
	int ret=0;
	for (int i = 0; i < 10; i++) {
		ret= pthread_create(&tid, NULL, tfun1, (void*) i);  // 返回线程id
		if (ret !=0 ) {
			perror("pthread_create fail");
			exit(-1);
		}
	}
	sleep(1);
	return 0;
}

2.3.pthred_exit

/**
 *  exit: 退出进程
 *  pthred_exit 退出线程
 */
void* tfun3(void* args){
	int j=(int )args;
	if(j==2){
	//	return NULL;  // 返回到函数调用者那里去
		pthread_exit(NULL);
	}
	printf("son thread...tfun1.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),j);
   // printf("---%d---",*j);
	return NULL;
}
int main0000017() {
	pthread_t tid;
	int ret=0;
	for (int i = 0; i < 10; i++) {
		ret= pthread_create(&tid, NULL, tfun3, (void*) i);  // 返回线程id
		if (ret == -1) {
			perror("pthread_create fail");
			exit(-1);
		}
	}
	sleep(1);

	return 0;
}

2.4.pthread_join 阻塞回收子线程 相当有 wait

/**
 * pthread_join 阻塞回收子线程 相当有 wait
 */
void* tfun4(void* args){
	return (void*)1100;
}
int main0000018() {
	pthread_t tid;
	//  成功返回0
    int ret= pthread_create(&tid, NULL, tfun4, NULL);  // 返回线程id
    if(ret !=0){
    	perror("pthread_create erro");
    	exit(-1);
    }
    int *retval;
    // 参数类型void**
    // 参数1 线程id  参数2 回调函数返回值 tfun4
    ret = pthread_join(tid,(void**)&retval);
    if(ret!=0){
     	perror("pthread_create erro");
        exit(-1);
    }
    // 返回值类型 -- return (void*)1100;
     printf("resutl---%d",retval);
	return 0;
}

2.4.1 回收多个线程

void* tfun5(void* args){
	return args;
}
int main0000019() {
	pthread_t tid[10];
		int ret=0;
		for (int i = 0; i < 10; i++) {
			ret= pthread_create(&(tid[i]), NULL, tfun5, (void*) i);  // 返回线程id
			if (ret == -1) {
				perror("pthread_create fail");
				exit(-1);
			}
		}
		 int *retval;
		sleep(1);
		for(int j=0;j<10;j++){
			pthread_join(tid[j],(void**)&retval);
			printf("-sleep---%d----%d\n",tid[j],retval);
		}
	return 0;
}

2.5.pthread_cancel

void* tfun11(void* args){
	while(1){
		int j=(int )args;
		     /**
			 *  调用pthread_cancel 以后如果子线程不进入系统调用比如
			 *  没有调用printf、sleep函数那么无法杀死子线程
			 *  如果没有上面函数,自己添加取消点:
			 *  调用: pthread_testcancel();
			 */
//		printf("son thread...tfun1.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),j);
//	    sleep(1);
		 pthread_testcancel();
	}

	return NULL;
}
/**
 * pthread_cancel 相当于kill
 */
int main0000020() {
	pthread_t tid;
	int ret=0;
	ret= pthread_create(&tid, NULL, tfun11, (void*) 1999);  // 返回线程id
	if (ret !=0 ) {
		perror("pthread_create fail");
		exit(-1);
	}
	int *retval;
	// 杀死线程
	/**
	 *  调用pthread_cancel 以后如果
	 */
	pthread_cancel(tid);
	// 如果线程被杀死了,返回-1
	pthread_join(tid,&retval);
	printf("return value-----  %d",retval);
	//sleep(10);
	return 0;
}

2.5.pthread_detach

void* tfun12(void* args){
		int j=(int )args;
		printf("son thread...tfun1.... pid = %d ...  %lu-args--%d \n",getpid(),pthread_self(),j);
	    sleep(1);
	    return NULL;
}
/***
 * pthread_detach
 */
int main0000021() {
	pthread_t tid;
		 int ret= pthread_create(&tid, NULL, tfun12, (void*) 1999);  // 返回线程id
		if (ret !=0 ) {
		 fprintf(stderr,"pthread_create fail--%s \n",strerror(ret));
			exit(1);
		}
		printf("---%d\n",ret);
		ret= pthread_detach(tid); //设置线pthread_join程分离,0表示成功
		printf("---%d\n",ret);
		// 分离开以后,线程执行完毕会被自动回收tid,没有了,后面pthread_join 来回收会出错
		if(ret!=0){
			 fprintf(stderr,"pthread_detach fail--%s \n",strerror(ret));
						exit(1);
		}

		sleep(3);
		// 功能判断是否分离开,分离,已经回收返回-1
	    int ret3 = pthread_join(tid,NULL);
		printf("---%d\n",ret3);
		//   #define EINVAL      22  /* Invalid argument */
	    if(ret3!=0){
	    	// strerror 无效,没有内容????
	    	 printf("%s\n",strerror(ret3));
	    }

	return 0;
}

2.6.线程属性设置

/***
 *  线程属性设置
 *  例子:通过线程属性设置线程自动detach
 */
int main() {
    pthread_t pid;
    pthread_attr_t attr,newattr;
    // 获取线程属性
    int ret = pthread_attr_init(&attr);
    if(ret!=0){
    	printf("pthread_attr_init--%s",strerror(ret));
    	exit(1);
    }
    ret = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED); // 设置线程分离属性
    if(ret!=0){
     	printf("pthread_attr_init--%s",strerror(ret));
     	exit(1);
     }
    pthread_t tid;
    ret = pthread_create(&tid,&attr,tfun12,NULL);
    if(ret!=0){
        	printf("pthread_create--%s",strerror(ret));
        	exit(1);
     }
    printf("main ..... pid:%d,tid=%lu\n",getpid(),pthread_self());

    // 获取线程属性
   // pthread_attr_getdetachstate(&newattr,PTHREAD_CREATE_DETACHED);


    ret = pthread_attr_destroy(&attr);
    if(ret!=0){
           	printf("pthread_attr_destroy--%s",strerror(ret));
           	exit(1);
        }
    sleep(5);
    // 验证设置是否有效,出错表示有效
    printf("----pthread_join 1---%d",ret);
    ret = pthread_join(tid,NULL);
    printf("----pthread_join 2---%d",ret);
    if(ret!=0){
               	printf("pthread_join--%s",strerror(ret));
               	exit(1);
            }
	return 0;
}
发布了53 篇原创文章 · 获赞 55 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/dreams_deng/article/details/104201715
今日推荐