Libtask:一个用于C和Unix的协同程序库,可以 编写事件驱动的程序而无需事件的麻烦! 可用于FreeBSD,Linux,OS X和Solaris

Libtask是一个简单的协程库。它运行在Linux(ARM,MIPS和x86)上,
FreeBSD(x86),OS X(PowerPC x86和x86-64)以及SunOS Solaris(Sparc),
并且很容易移植到其他系统。

Libtask为程序员提供了线程的错觉,但是
操作系统只能看到一个内核线程。
为清楚起见,我们将协同程序称为“任务”,而不是线程。

调度是合作的。一次只运行一个任务,
如果没有明确放弃,就无法重新安排
CPU。task.h中提供的大多数函数都有
睡觉的可能性。使用该任务的程序
函数应该#include < task.h >。

*基本任务操作

int taskcreate(void(* f)(void * arg),void * arg,unsigned int stacksize);

	在堆栈大小stacksize上创建一个运行f(arg)的新任务。

void tasksystem(void);

	将当前任务标记为“系统”任务。这些被忽略了
	为了决定程序已经完成运行
	(参见下一篇taskexit)。
	
void taskexit(int status);

	退出当前任务。如果这是最后一次非系统任务,
	使用给定的退出状态退出整个程序。

void taskexitall(int status);

	使用给定的退出状态退出整个程序。

void taskmain(int argc,char * argv []);

	写这个函数而不是main。Libtask提供自己的主要功能。

int taskyield(void);
	
	明确放弃CPU。将安排当前任务
	所有其他当前准备好的任务都有机会再次出现
	跑步。返回在运行时运行的其他任务的数量
	目前的任务正在等待 (零意味着没有其他任务
	试图跑。)

int taskdelay(unsigned int ms)

	显式放弃CPU至少ms毫秒。
	在此期间,其他任务继续运行。

void ** taskdata(void);

	返回指向单个每任务void *指针的指针。
	您可以将其用作每个任务存储位置。

void needstack(int n);

	告诉任务库你需要至少n个字节
	在堆栈上。如果没有,任务库将调用abort。
	(很难弄清楚堆栈的大小。我通常会这么做
	他们真的很大(比如32768),然后不用担心。)

void taskname(char *,...);

	采用像printf这样的参数列表。设置当前任务的名称。
	
char * taskgetname(void);

	返回当前任务的名称。是实际的缓冲区; 不要自由。
	
void taskstate(char *,...);
char * taskgetstate(void);

	与taskname和taskgetname类似,但适用于任务状态。
	
	当你发送一个任务程序一个SIGQUIT(或BSD上的SIGINFO)
	它将打印所有任务及其名称和状态的列表。
	这对于调试程序没有做任何事情的原因很有用!

unsigned int taskid(void);

	返回当前任务的唯一任务ID。

*非阻塞I / O.

对非阻塞I / O有少量的运行时支持
在文件描述符上。  

int fdnoblock(int fd);

	将给定fd上的I / O设置为非阻塞。应该
	在任何其他fd例程之前调用。

int fdread(int,void *,int);

	像常规的read()一样,但是在等待时将任务置于睡眠状态
	数据而不是阻止整个程序。

int fdwrite(int,void *,int);

	像常规的write()一样,但是在等待时将任务置于睡眠状态
	写入数据而不是阻止整个程序。

void fdwait(int fd,int rw);

	坐在fdread和fdwrite下面的低级调用。
	在fd上等待I / O可以使任务进入休眠状态。
	Rw指定I / O的类型:'r'表示读,'w'表示写,
	其他任何意味着只有特殊情况(挂断等)
	'r'和'w'也因特殊情况而醒来。

*网络I / O.

这些是丑陋的Unix套接字例程的方便包装。
他们都可以在通话期间将当前任务置于睡眠状态。  

int netannounce(int proto,char * address,int port)

	启动在协议的地址和端口上运行的网络侦听器。
	Proto是TCP或UDP。端口号是端口号。地址是一个
	主机名或IP地址的字符串版本。如果地址为空,
	然后宣布绑定到所有可用接口上的给定端口。
	返回与netaccept一起使用的fd。
	示例:netannounce(TCP,“localhost”,80)或 
		netannounce(TCP,“127.0.0.1”,80)或netannounce(TCP,0,80)。

int netaccept(int fd,char * server,int * port)

	获取进入侦听器fd的下一个连接。
	返回一个用于与刚刚连接的人交谈的fd。
	如果server不为null,则它必须至少指向一个缓冲区
	用远程IP地址填写的16个字节。
	如果port不为null,则使用报告端口填充它。
	例:
		char server [16];
		int port;
		
		if(netaccept(fd,server,&port)> = 0)
			printf(“从%s:%d连接”,服务器,端口);

int netdial(int proto,char * name,int port)

	创建与特定主机的新(传出)连接。
	名称可以是IP地址或域名。如果是域名,
	在解析名称时整个程序将被阻止
	(DNS库不提供良好的非阻塞接口)。
	示例:netdial(TCP,“www.google.com”,80)
		或netdial(TCP,“18.26.4.9”,80)

* 时间

unsigned int taskdelay(unsigned int ms)

	将当前任务置于休眠状态大约ms毫秒。
	返回睡眠的实际时间量,以毫秒为单位。

*示例程序

在这个目录中,tcpproxy.c是一个简单的TCP代理,用于说明
以上大部分内容。你可以跑

	tcpproxy 1234 www.google.com 80

然后你应该能够访问http:// localhost:1234 /并查看谷歌。

其他例子是:
	primes.c - 简单的主筛
	 httpload.c - 简单的HTTP负载生成器
	 testdelay.c -  test taskdelay()

* 建造

要构建,运行make。您可以运行make install来复制task.h和
libtask.a到/ usr / local中的适当位置。然后你
应该能够在您的程序中与-ltask链接
使用它。  

在SunOS Solaris计算机上,运行makesun而不是make。

*联系信息

如有疑问或问题,请给我发电子邮件

拉斯考克斯
rsc@swtch.com


*你最初可能不会使用的东西
*但最终可能想知道

void tasksleep(Rendez *);
int taskwakeup(Rendez *);
int taskwakeupall(Rendez *);

	Rendez是一个条件变量。您可以声明一个新的
	只是为它分配内存(或将其放在另一个结构中)
	然后归零内存。Tasksleep(r)'睡在r',给予
	上升CPU。多个任务可以在单个Rendez上休眠。
	当另一个任务出现并调用taskwakeup(r)时, 
	睡在r上的第一个任务(如果有的话)将被唤醒。
	Taskwakeupall(r)唤醒在r上睡觉的所有任务。
	它们都返回唤醒的实际任务数。



void qlock(QLock *);
int canqlock(QLock *);
void qunlock(QLock *);

	由于合作,你可能不需要锁 
	调度,但如果你这样做,这里有一些。你可以做一个新的
	QLock只是声明它并将内存归零。
	如果锁定由其他人持有,则调用qlock将放弃CPU。
	调用qunlock不会放弃CPU。
	调用canqlock尝试锁定锁,但不会放弃CPU。
	如果获取了锁,则返回1,如果此时不能,则返回0。

void rlock(RWLock *);
int canrlock(RWLock *);
void runlock(RWLock *);

void wlock(RWLock *);
int canwlock(RWLock *);
void wunlock(RWLock *);

	RWLocks是读写器锁。任意数量的读者
	可以一次锁定它们,但一次只能锁定一个。
	如果作家持有它,就不会有任何读者。
	

Channel * chancreate(int,int);
等等

	通道是缓冲的通信管道
	用于在任务之间发送消息。有些人喜欢
	使用渠道完成大部分任务间通信。
	
	有关频道的详细信息,请参阅频道的说明
	http://swtch.com/usr/local/plan9/man/man3/thread.html和
	http://swtch.com/~rsc/thread/
	并且还示例程序primes.c,它实现
	并行的筛选。


源码:https://swtch.com/libtask/
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值