【C/C++】【Linux】Linux系统调用——线程控制

  • Post author:
  • Post category:linux


Linux系统调用——线程控制

什么叫线程?


线程是CPU调度和分派的基本单位。

是比进程更小的能独立运行的基本单位。除了一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),线程基本上不拥有系统资源,但

可与同属一个进程的其他线程共享进程所拥有的全部资源。

线程与进程的区别?线程的优缺点?

(1)

进程是系统资源分配的最小单位,线程是CPU调度和分派的基本单位。

(2)

进程拥有独立的堆栈空间和数据段

,每当启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这对于多进程来说十分“奢侈”。

线程拥有独立的堆栈空间,但是共享数据段

,它们彼此之间使用相同的地址空间,共享大部分数据,比进程更节俭,开销比较小,而且

线程彼此间切换的速度比进程更快效率更高

。正因为进程有独立的地址空间,所以

一个进程崩溃,不会影响其他进程,进程更具有健壮性

。而线程只是一个进程中的不同执行路径,

一个线程死掉就等于整个进程死掉

(3)

通信机制

上,进程间通信相对很复杂,譬如管道,信号,消息队列,共享内存,套接字等通信机制,而线程由于共享数据段所以通信机制很方便。

(4)

线程


使多CPU系统更加有效。

操作系统会保证当线程数不大于CPU数目时,不同的线程运行于不同的CPU上。

(5)

改善程序结构。

一个既长又复杂的进程可以考虑分为多个线程,成为几个独立或半独立的运行部分,这样的程序会利于理解和修改。

线程控制函数


1.phthread_create()

函数用法

#include <pthread.h>

int pthread_create(pthread_t *restrict thread,

const pthread_attr_t *restrict attr,

void *(*start_routine)(void*), void *restrict arg);

函数功能

创建线程

参数1,thread:线程ID,用时取地址。&tid。

参数2,attr:线程属性,一般为NULL

参数3,start_routine:线程处理函数,自定义的函数,函数类型为void*,决定该线程要做的动作

参数4,arg:线程处理函数的入参

函数返回值 线程创建成功返回0,否则返回错误码。


2.pthread_join()

函数用法

#include <pthread.h>

int pthread_join(pthread_t thread, void **value_ptr);

函数功能

等待线程结束,并回收线程运行时的资源

参数1,thread:线程ID

参数2,value_ptr:存储被等待的线程的返回值

函数返回值 成功返回0,否则返回错误码。


3.pthread_exit()

函数用法

#include <pthread.h>

void pthread_exit(void *value_ptr);

函数功能

退出当前线程

参数,value_ptr:存储被退出的线程的返回值

函数返回值 无返回值


4.pthread_cancel()

函数用法

#include <pthread.h>

int pthread_cancel(pthread_t thread);

函数功能

取消另一个线程

参数,thread:要被取消的线程的线程ID

通常和pthread_sentcanceltype()配合使用

函数返回值 成功返回0,否则返回错误码。


5.pthread_setcanceltype()

函数用法

#include <pthread.h>

int pthread_setcanceltype(int type, int *oldtype);

函数功能

这是当前线程的取消属性

参数1,type:取消类型,有两个选项

PTHREAD_CANCEL_DEFERRED               延迟取消

PTHREAD_CANCEL_ASYNCHRONOUS    立即取消

参数2,oldtyp:保存以前的取消类型。

函数返回值 成功返回0,否则返回错误码。


6.pthread_detach()

函数用法

#include <pthread.h>

iint pthread_detach(pthread_t thread);

函数功能

分离当前线程,并且在结束时回收资源

参数,thread:要分离的线程ID

通常和pthread_self()配合使用

函数返回值 成功返回0,否则返回错误码。


7.pthread_self()

函数用法

#include <pthread.h>

pthread_t pthread_self(void);

函数功能 返回当前线程ID
函数返回值 返回当前线程ID

实例

1.线程控制函数的简单运用

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

pthread_t tid1, tid2;

void delay()
{
	int x = 10000;
	int y;
	while(x > 0)
	{
		y = 20000;
		while(y > 0)
		{
			y--;
		}
		x--;
	}
}

void *Mypthread1(void * arg)
{
	int old;
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,&old);//设置线程取消属性,立即取消
	printf("HelloWorld!\n");
	delay();
	pthread_exit((void *)100);//线程退出
}

void *Mypthread2(void * arg)
{
	printf("%s\n", arg);
	pthread_cancel(tid1);//取消线程
	//exit(1);//进程退出
}

int main()
{
	int ret;

	ret = pthread_create(&tid1, NULL, Mypthread1, NULL);//创建线程1
	if (ret != 0)
	{
		perror("pthread_create1");
		exit(1);
	}

	ret = pthread_create(&tid2, NULL, Mypthread2, "HELLOWORLD!");//创建线程2
	if (ret != 0)
	{
		perror("pthread_create2");
		exit(1);
	}

	void *status;
	ret = pthread_join(tid1, &status);//两个作用 1、等待  2、回收
	if (0 != ret)
	{
		perror("pthread_join1");
	}
	printf("Mypthread1 Exit is %d\n", status);
	ret = pthread_join(tid2, &status);
	if (ret != 0)
	{
		perror("pthread_join2");
	}
	return 0;
}

2.之前我们通过用进程来实现使消息队列能发能收,这次使用线程来实现。

msg_send_pthread.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#define MSGKEY 1234

struct msgbuf
{
	long mtype;     /* message type, must be > 0 */
	char mtext[100];  /* message data */
};


pthread_t tid1, tid2;

void *SendData(void *arg)
{
	int old;
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);//设置线程取消属性为立即取消

	int ret;
	struct msgbuf mbuf;
	int msgid = *(int *)arg;

	while (1)
	{
		memset(mbuf.mtext, 0, sizeof(mbuf.mtext));
		scanf("%s", mbuf.mtext);

		mbuf.mtype = 1;
		ret = msgsnd(msgid, &mbuf, sizeof(mbuf.mtext), 0);
		if (-1 == ret)
		{
			perror("msgsnd");
			exit(1);
		}

		if (!strcmp(mbuf.mtext, "bye"))
		{
			mbuf.mtype = 2;
			msgsnd(msgid, &mbuf, sizeof(mbuf.mtext), 0);
			break;
		}
	}

}

void *RecvData(void *arg)
{
	int ret;
	struct msgbuf mbuf;
	int msgid = *(int *)arg;

	while (1)
	{
		memset(mbuf.mtext, 0, sizeof(mbuf.mtext));
		ret = msgrcv(msgid, &mbuf, sizeof(mbuf.mtext), 2,0);
		if (-1 == ret)
		{
			perror("msgrcv");
			exit(1);
		}

		if (!strcmp(mbuf.mtext, "bye"))
		{
			pthread_cancel(tid1);//取消线程1
			break;
		}

		printf("\t%s\n", mbuf.mtext);

	}
}

int main()
{
	int ret;
	int msgid;

	msgid = msgget(MSGKEY, IPC_CREAT | IPC_EXCL);	//创建消息队列
	if (-1 == msgid)
	{
		perror("msgget");
		exit(1);
	}

	ret = pthread_create(&tid1, NULL, SendData, &msgid);//创建线程,发送数据
	if (ret != 0)
	{
		perror("pthread_create1");
		exit(1);
	}

	ret = pthread_create(&tid2, NULL, RecvData, &msgid);//创建线程,接收数据
	if (ret != 0)
	{
		perror("pthread_create2");
		exit(1);
	}

	void *status;
	ret = pthread_join(tid1, &status);
	if (ret != 0)
	{
		perror("pthread_join1");
	}

	ret = pthread_join(tid2, &status);
	if (ret != 0)
	{
		perror("pthread_join2");
	}

	msgctl(msgid, IPC_RMID, NULL);//销毁消息队列
	return 0;
}

msg_recv_pthread.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <pthread.h>
#include <string.h>
#include <stdlib.h>
#define MSGKEY 1234

struct msgbuf
{
	long mtype;     /* message type, must be > 0 */
	char mtext[100];  /* message data */
};


pthread_t tid1, tid2;

void *SendData(void *arg)
{
	int old;
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);//设置线程取消属性为立即取消

	int ret;
	struct msgbuf mbuf;
	int msgid = *(int *)arg;

	while (1)
	{
		memset(mbuf.mtext, 0, sizeof(mbuf.mtext));
		scanf("%s", mbuf.mtext);

		mbuf.mtype = 2;
		ret = msgsnd(msgid, &mbuf, sizeof(mbuf.mtext), 0);
		if (-1 == ret)
		{
			perror("msgsnd");
			exit(1);
		}

		if (!strcmp(mbuf.mtext, "bye"))
		{
			mbuf.mtype = 1;
			msgsnd(msgid, &mbuf, sizeof(mbuf.mtext), 0);
			break;
		}
	}

}

void *RecvData(void *arg)
{
	int ret;
	struct msgbuf mbuf;
	int msgid = *(int *)arg;

	while (1)
	{
		memset(mbuf.mtext, 0, sizeof(mbuf.mtext));
		ret = msgrcv(msgid, &mbuf, sizeof(mbuf.mtext), 1,0);
		if (-1 == ret)
		{
			perror("msgrcv");
			exit(1);
		}

		if (!strcmp(mbuf.mtext, "bye"))
		{
			pthread_cancel(tid1);//取消线程1
			break;
		}

		printf("\t%s\n", mbuf.mtext);

	}
}

int main()
{
	int ret;
	int msgid;

	msgid = msgget(MSGKEY, 0);	//获取消息队列
	if (-1 == msgid)
	{
		perror("msgget");
		exit(1);
	}

	ret = pthread_create(&tid1, NULL, SendData, &msgid);//创建线程,发送数据
	if (ret != 0)
	{
		perror("pthread_create1");
		exit(1);
	}

	ret = pthread_create(&tid2, NULL, RecvData, &msgid);//创建线程,接收数据
	if (ret != 0)
	{
		perror("pthread_create2");
		exit(1);
	}

	void *status;
	ret = pthread_join(tid1, &status);
	if (ret != 0)
	{
		perror("pthread_join1");
	}

	ret = pthread_join(tid2, &status);
	if (ret != 0)
	{
		perror("pthread_join2");
	}

	return 0;
}



版权声明:本文为qq_42379345原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。