xenomai鍐呮牳瑙f瀽涔嬩俊鍙穝ignal(浜?---xenomai淇″彿澶勭悊鏈哄埗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了xenomai鍐呮牳瑙f瀽涔嬩俊鍙穝ignal(浜?---xenomai淇″彿澶勭悊鏈哄埗相关的知识,希望对你有一定的参考价值。

鏍囩锛?a href='http://www.mamicode.com/so/1/ctr' title='ctr'>ctr   灏变細   conf   妯″紡   澶辫触   sigwait   type   errno   rmi   

xenomai淇″彿

涓婄瘒鏂囩珷璁蹭簡linux鐨勪俊鍙峰湪鍐呮牳鐨勫彂閫佷笌澶勭悊娴佺▼锛岀幇鍦ㄥ姞鍏ヤ簡cobalt鏍革紝Cobalt鍐呮牳涓簒enomai绾跨▼鎻愪緵浜嗕俊鍙锋満鍒躲€備笅闈竴涓€瑙f瀽xenomai鍐呮牳鐨勪俊鍙峰鐞嗘満鍒躲€?/p>

1 鍙屾牳涓嬬殑淇″彿鍒嗙被

鎴戜滑宸茬粡鐭ラ亾锛屾瘡涓敤鎴风┖闂寸殑xenomai绾跨▼鍦ㄥ唴鏍哥┖闂撮兘鏈変袱涓皟搴﹀疄浣擄紝涓€鏄湪linux鍐呮牳涓殑task_struct锛屽彟涓€涓槸绉颁负linux绌洪棿鐨勪竴涓奖瀛?shadow)鐨剎nthread銆傚畠浠〃绀虹殑鏄悓涓€涓嚎绋嬶紝linux璋冨害鐨勬槸task_struct锛屽疄鏃舵牳cobalt璋冨害鐨勬槸xnthread銆傚彲閫氳繃鍦ㄤ袱涓皟搴﹀櫒闂磋縼绉荤殑鏂瑰紡鏉ヨxenomai绾跨▼鍦╨inux鏍稿拰Cobalt鏍镐笂杩愯銆?/p>

鎶€鏈浘鐗? src=

linux杩涚▼涓庣嚎绋嬬殑淇″彿灏辫浜哄ご鐤肩殑浜嗭紝鍐嶆潵涓€涓獂enomai淇″彿宀備笉鏇村鏉傦紵鍏跺疄涓嶅鏉傦紝鍙渶瑕佸垎娓呬笁绉嶄俊鍙峰強鍏朵綔鐢ㄥ煙灏監K锛屽鍥炬墍绀猴紝杩涚▼A鍐呮湁涓や釜瀹炴椂绾跨▼鍜屼竴涓櫘閫氱嚎绋嬶紝杩涚▼B鍐呮湁涓€涓疄鏃剁嚎绋嬪拰涓€涓櫘閫氱嚎绋嬶紝瀹冧滑涔嬮棿鐨勪俊鍙峰垎涓轰袱绫伙細

  • 浣跨敤linux淇″彿鏈哄埗锛?/strong>杩涚▼闂翠俊鍙枫€乴inux绾跨▼闂翠俊鍙凤紱
  • 浣跨敤xenomai淇″彿鏈哄埗:鍙瓨鍦ㄤ簬xenomai绾跨▼闂达紝xenomai鍐呯殑浠讳綍淇″彿閮戒笉浼氫紶鎾埌linux杩涚▼绌洪棿锛屼篃涓嶄細瀵艰嚧杩涚▼閫€鍑?/strong>锛?/li>

鐢变簬涓€涓獂enomai绾跨▼瀹冩棦鏄痩inux浠诲姟涔熸槸cobalt浠诲姟锛屼笉鍚岀殑淇″彿浜х敓鍜屽鐞嗗湪涓嶅悓鐨勫唴鏍镐腑銆傚浜巐inux淇″彿锛岀敱linux璋冨害鍣紙linux鍐呮牳锛夊彂閫佸拰鎺ユ敹澶勭悊锛泋enomai淇″彿鐢眡enomai绾跨▼閫氳繃cobalt鍐呮牳鎺ュ彛鍙戦€佹垨鎺ユ敹锛屽彲鐢ㄤ簬鍚屾浜掓枼锛堝彲涓庝俊鍙烽噺semaphore瀵规瘮锛夛紝瀵逛簬涓€涓獂enomai搴旂敤涓殑linux淇″彿锛?/p>

  • xenomai绾跨▼閫氳繃__STD(kill/pthread_kill)閫氳繃linux鍙戦€佺殑淇″彿锛岃皟鐢ㄦ椂浼氳嚜鍔ㄨ縼绉诲埌linux鍐呮牳(root鍩?鍐嶅彂閫侊紱(__STD()瀹忚〃绀烘樉寮忚皟鐢↙inux鏍囧噯搴撳嚱鏁帮級
  • xenomai绾跨▼鎺ユ敹linux淇″彿澶勭悊鏃朵篃鏄竴鏍凤紝蹇呴』杩佺Щ鍒發inux鍐呮牳鎵嶈兘澶勭悊;

瀵逛簬linux鍚憍enomai鍙戦€佷俊鍙?/strong>锛屼緥濡傛垜浠粓绔腑鍚姩涓€涓獂enomai浠诲姟鍚庯紝閫氳繃閿叆ctrl+c缁撴潫xenomai浠诲姟鐨勬搷浣滐紝linux鍦ㄦ煡鎵惧鐞嗚淇″彿鐨勪换鍔℃椂锛屽鏋滈渶瑕佸鐞嗕俊鍙风殑鏄竴涓疄鏃朵换鍔★紝浼氭妸xenomai浠诲姟杩佺Щ鍒發inux鏍镐笂锛屽啀鎸塴inux鐨勫鐞嗛偅濂楁祦绋嬪幓澶勭悊灏辫銆?/strong>涓嬮潰浠湅瀹冩槸鎬庝箞澶勭悊鐨勶紝涓庝笂涓€绡囨枃绔爈inux涓嬬殑淇″彿澶勭悊娴佺▼瀵规瘮锛屽叾涓叾涓笉涓€鏍风殑姝ラ濡備笅,鍏朵綑鐨勪笌linux澶勭悊鏂瑰紡涓€鑷淬€?/p>

  1. linux杩涚▼鎴栬€?shell 鍙戦€佷竴涓俊鍙风粰xenomai绾跨▼A锛屽彲浠ヨ皟鐢?kill锛宼kill锛宼gkill锛宺t_sigqueueinfo
  2. 鍥涗釜鍙戦€佷俊鍙风殑鍑芥暟锛屽湪鍐呮牳涓渶缁堥兘鏄皟鐢?do_send_sig_info
  3. do_send_sig_info 璋冪敤 send_signal 缁檟enomai浠诲姟A 鍙戦€佷竴涓俊鍙凤紝鍏跺疄灏辨槸鎵惧埌 A 鐨?code>task_struct锛屼笉鍙潬淇″彿鍔犲叆淇″彿闆嗗悎锛屽彲闈犱俊鍙?鍔犲叆淇″彿閾捐〃銆傜劧鍚庤皟鐢?code>complete_signal()澶勭悊淇″彿銆?/li>
  4. complete_signal()璋冪敤 signal_wake_up()->signal_wake_up_state()鍞ら啋A銆?/li>

鍙屾牳涓嬶紝xenomai鍦╯ignal_wake_up_state鍑芥暟涓彃鍏ヤ簡妫€娴嬩唬鐮佸涓嬨€?/p>

void signal_wake_up_state(struct task_struct *t, unsigned int state)
{
	set_tsk_thread_flag(t, TIF_SIGPENDING);

	/* TIF_SIGPENDING must be prior to reporting.TIF_SIGPENDING */
	__ipipe_report_sigwake(t);
    
	if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
		kick_process(t);
}

鎻掑叆浠g爜__ipipe_report_sigwake(t),__ipipe_report_sigwake()璋冪敤__ipipe_notify_kevent()鍙戝嚭涓€涓唴鏍搁棿淇″彿浜嬩欢IPIPE_KEVT_SIGWAKE锛?code>__ipipe_notify_kevent璋冪敤Cobalt鍐呮牳鐨刬pipe_kevent_hook鏉ユ帴鏀惰繖浜涗簨浠躲€?/p>

int ipipe_kevent_hook(int kevent, void *data)
{
	int ret;

	switch (kevent) {
	case IPIPE_KEVT_SCHEDULE:
		ret = handle_schedule_event(data);/**/
		break;
	case IPIPE_KEVT_SIGWAKE:
		ret = handle_sigwake_event(data);///IPIPE_KEVT_SIGWAKE
		break;
	......
	default:
		ret = KEVENT_PROPAGATE;
	}
	return ret;
}

ipipe_kevent_hook涓牴鎹簨浠剁被鍨嬫墽琛宧andle_sigwake_event銆?/p>

static int handle_sigwake_event(struct task_struct *p)
{
	struct xnthread *thread;
	sigset_t pending;
	spl_t s;

	thread = xnthread_from_task(p);
	......
	xnlock_get_irqsave(&nklock, s);
	......

	if (xnthread_test_state(thread, XNRELAX)) {
		xnlock_put_irqrestore(&nklock, s);
		return KEVENT_PROPAGATE;
	}
	......
	if (p->state & (TASK_INTERRUPTIBLE|TASK_UNINTERRUPTIBLE))
		cobalt_set_task_state(p, p->state | TASK_NOWAKEUP);

	__xnthread_kick(thread);

	xnsched_run();

	xnlock_put_irqrestore(&nklock, s);

	return KEVENT_PROPAGATE;
}

handle_sigwake_event()涓殑閫昏緫寰堢畝鍗曪紝鍏堢湅A鏄繍琛屽湪root鍩熻繕鏄痟aed鍩燂紝濡傛灉鏈潵灏卞湪root鍩燂紙澶勪簬XNRELAX鐘舵€侊級锛屽嵆鍦╨inux鏍镐笂璋冨害锛岄偅涔堜笉鐢ㄥ仛浠€涔堟搷浣滐紝鍙洿鎺ュ鐞嗕俊鍙凤紱濡傛灉A鐜板湪鏄痟ead鍩熻皟搴︼紝鍏堢湅鐪嬪畠鏄笉鏄彲涓柇鐫$湢鐘舵€侊紙TASK_INTERRUPTIBLE|TASK_UNINTERRUPTIBLE锛夛紝鐒跺悗璋冪敤__xnthread_kick()灏嗕换鍔韪㈠嚭haed鍩熴€傛渶鍚庤皟鐢?code>xnsched_run灏咰PU璁╃粰linux璋冨害鍣ㄤ互灏藉揩鍞ら啋浠诲姟A杩涜淇″彿澶勭悊銆傚悗闈㈢殑澶勭悊涓巐inux涓€鑷淬€?/p>

瀵逛簬xenomai鍚憀inux鍙戦€佷俊鍙?/strong>锛岄渶瑕佸湪xenomai浠诲姟浠g爜鍐呮樉鎬ц皟鐢ㄥ嚱鏁?code>kill()鎴杙thread_kill()鍙戦€併€備笖蹇呴』閫氳繃__STD()淇グkill()鍑芥暟锛岀紪璇戞椂鎵嶄細鐩存帴浣跨敤glibc鐨刱ill鍑芥暟,瀵筽thread_kill涔熸槸涓€鏍枫€備笉鍔犱慨楗扮殑kill()鎴杙thread_kill()鍑芥暟浼氬湪缂栬瘧鏃堕粯璁ら摼鎺ュ埌libcobalt瀹氫箟鐨勫嚱鏁般€?/p>

COBALT_IMPL(int, kill, (pid_t pid, int sig))
{
	int ret;
	if (pid <= 0)
		return __STD(kill(pid, sig));

	ret = XENOMAI_SYSCALL2(sc_cobalt_kill, pid, sig);
	if (ret) {
		if (ret == -ESRCH)
			return __STD(kill(pid, sig));
....
	}
	return 0;
}
COBALT_IMPL(int, pthread_kill, (pthread_t thread, int sig))
{
	int ret;

	ret = -XENOMAI_SYSCALL2(sc_cobalt_thread_kill, thread, sig);
	if (ret == ESRCH)
		return __STD(pthread_kill(thread, sig));

	return ret;
}

涓や釜鍑芥暟閮芥槸鍏堝皾璇曡xenomai鍐呮牳澶勭悊锛屽湪xenomai鍐呮牳鏈€缁堥兘浼氳皟鐢?code>__cobalt_kill();濡傛灉璇id涓嶆槸xenomai绾跨▼锛屾墠浼氳浆鑰岃皟鐢╣libc鐨刱ill鍑芥暟锛岄€氳繃linux鍐呮牳澶勭悊銆?/p>

鎬讳箣锛屼娇鐢╨inux淇″彿鐨勬搷浣滐紝涓嶇鏄疄鏃惰繕鏄潪瀹炴椂閮藉繀椤诲湪linux璋冨害鍣ㄤ笂杩愯鎵嶈兘瀹屾垚鎿嶄綔銆?/p>

2 xenomai淇″彿

xenomai绾跨▼闂寸殑淇″彿澶勭悊鏈哄埗鐢眡enomai鍐呮牳瀹炵幇锛屼笌linux绾跨▼淇″彿绫讳技锛屼絾娌℃湁linux绾跨▼淇″彿閭d箞澶嶆潅,瀹冦€?/p>

鏃㈢劧鏄痻enomai绾跨▼闂寸殑锛岄偅灏辫绫讳技鐨勫儚linux閭f牱瀹炵幇xenomai鍐呮牳鐨勪竴濂椾俊鍙风鐞嗘満鍒躲€傞鍏堟槸姣忎釜xenomai绾跨▼鐨勫唴鏍哥鐞嗙粨鏋刢obalt_thread閲岄潰鍏充簬淇″彿澶勭悊鐨勫瓧娈点€?/p>

struct cobalt_process {
	......
	struct list_head sigwaiters;
	......
};
struct cobalt_thread {
	......
    struct xnthread threadbase;
    struct cobalt_process *process;
    ......
	/** Signal management. */
	sigset_t sigpending;
	struct list_head sigqueues[_NSIG]; /* in cobalt_sigpending */
	struct xnsynch sigwait;
	struct list_head signext;
	......
};

sigpending琛ㄧず鍝簺淇″彿灏氱瓑寰呭鐞嗭紙鏈喅锛夛紝杩欓噷鍙槸琛ㄧず鏌愪釜淇″彿寰呭鐞嗭紝璇ヤ俊鍙峰叿浣撴湁澶氬皯涓渶瑕佺湅sigqueues[]锛?code>sigqueues[]淇″彿闃熷垪锛屽畠鐨勫ぇ灏忔槸_NSIG锛屼篃灏辨槸璇存瘡涓俊鍙烽兘鏈変釜闃熷垪銆?code>sigwait涓€涓祫婧愬悓姝ュ璞?xnsynch)琛ㄧず锛屾垜浠湪13.2 璧勬簮鍚屾瀵硅薄鈥攛nsynch灏忚妭瑙f瀽浜唜nsynch鏄共浠€涔堢敤鐨勶紝淇″彿涔熸槸涓€绉嶈祫婧愶紝鎵€浠ヨ繖閲岀敤鏉ョ瓑寰呬竴涓俊鍙疯祫婧?褰撶敤鎴疯皟鐢╯igwait绯荤粺璋冪敤绛夊緟涓€涓俊鍙风殑鏃跺€欙紝灏变細鍦?code>sigwait涓婄潯鐪犵瓑寰呬俊鍙枫€?code>signext鍦╯igwait鏃剁敤鏉ュ姞鍏obalt_process涓殑sigwaiters閾捐〃銆?/p>

xenomai鐨勪俊鍙蜂笌linux涓€鑷达紝1-31鍙蜂俊鍙蜂笉鏀寔鎺掗槦锛?1-64鍙蜂俊鍙锋敮鎸佹帓闃熴€?/p>

闇€瑕佹敞鎰忕殑鏄痻enomai鍐呯殑淇″彿闄や笌linux涓€鑷村杩樻湁鍑犱釜鐗规湁鐨勪俊鍙凤紝杩欎簺淇″彿鏄笉鍏紑鐨勶紝浠呭瓨鍦ㄤ簬xenomai鍐呮牳涓巐ibcobalt鍐呴儴锛涜繖浜涗俊鍙锋棤娉曞睆钄斤紝涓嶈兘杩涜鎺掗槦锛屼篃鏃犳硶灏嗗畠浠缃负淇″彿闆嗐€?/p>

/*archx86includeuapiasmsignal.h*/
#define SIGRTMIN	32
#define SIGRTMAX	_NSIG 

/*includexenomaicobaltuapisignal.h*/
#define SIGSUSP (SIGRTMAX + 1)
#define SIGRESM (SIGRTMAX + 2)
#define SIGRELS (SIGRTMAX + 3)
#define SIGKICK (SIGRTMAX + 4)
#define SIGDEMT (SIGRTMAX + 5)

SIGSUSP 瀵规寚瀹氱嚎绋媠uspend鎿嶄綔锛?code>SIGRESM 瀵规寚瀹氱嚎绋媟esume鎿嶄綔锛?code>SIGRELS 瀵规寚瀹氱嚎绋嬭В闃诲;SIGKICK 杩娇鎸囧畾绾跨▼閫€鍑轰富妯″紡;SIGDEMT灏嗘寚瀹氱嚎绋嬮檷绾т负闈炲疄鏃剁嚎绋嬶紝璇ュ奖瀛愮嚎绋嬩粛鍙闂甔enomai璧勬簮锛屼絾涓嶅啀绔炰簤瀹炴椂璋冨害銆?/p>

xenomai淇″彿鐩稿叧鎺ュ彛锛岀敱libcobalt瀹炵幇銆傚涓?/p>

int sigwaitinfo(const sigset_t *set, siginfo_t *si);
int sigwait(const sigset_t *set, int *sig);
int sigtimedwait (const sigset_t *set, siginfo_t *si,
				const struct timespec *timeout);
int sigpending(sigset_t *set);
int kill(pid_t pid, int sig);
int sigqueue(pid_t pid, int sig, const union sigval value);
int pthread_kill(pthread_t thread, int sig);

/*libcobaltsignal.c*/ COBALT_IMPL(int, kill, (pid_t pid, int sig)) { int ret; if (pid <= 0) return __STD(kill(pid, sig)); ret = XENOMAI_SYSCALL2(sc_cobalt_kill, pid, sig); if (ret) { if (ret == -ESRCH) return __STD(kill(pid, sig)); .... } return 0; } /*libcobalt hread.c*/ COBALT_IMPL(int, pthread_kill, (pthread_t thread, int sig)) { int ret; ret = -XENOMAI_SYSCALL2(sc_cobalt_thread_kill, thread, sig); if (ret == ESRCH) return __STD(pthread_kill(thread, sig)); return ret; }

鍏堥€氳繃绯荤粺璋冪敤璁﹛enomai鍐呮牳澶勭悊锛屾瘡涓敤鎴风嚎绋嬪湪鍐呮牳閮芥槸涓€涓换鍔★紝閮藉叿鏈塸id锛屼笉绠℃槸pid杩樻槸pthread_t锛屾渶缁堥兘浼氳浆鎹负xenomai绾跨▼鍐呮牳缁撴瀯cobalt_thread锛屽啀瀵筩obalt_thread杩涜淇″彿鐩稿叧鎿嶄綔銆傚鏋滀笉鑳借浆鎹㈣鏄庤pid鎴杙thread_t琛ㄧず鐨勭嚎绋嬩笉鏄竴涓獂enomai绾跨▼锛屽氨浼氳繑鍥濫SRCH銆傝浆鑰岃皟鐢╣libc鐨刾thread_kill銆乲ill鍑芥暟杩涜€岃linux鍘诲鐞嗐€?/p>

/*kernelxenomaiposix	hread.c*/
COBALT_SYSCALL(thread_kill, conforming,
	       (unsigned long pth, int sig))
{
	struct cobalt_local_hkey hkey;
	struct cobalt_thread *thread;
	int ret;
	spl_t s;
......
	hkey.u_pth = pth;
	hkey.mm = current->mm;
	thread = thread_lookup(&hkey);
	if (thread == NULL)
		ret = -ESRCH;
	else
		ret = __cobalt_kill(thread, sig, 0);
.....
	return ret;
}
/*kernelxenomaiposixsignal.c*/
COBALT_SYSCALL(kill, conforming, (pid_t pid, int sig))
{
	struct cobalt_thread *thread;
	int ret;
	spl_t s;

	thread = cobalt_thread_find(pid);/*鎵惧埌绾跨▼*/
	if (thread == NULL)
		ret = -ESRCH;
	else
		ret = __cobalt_kill(thread, sig, 1);

	return ret;
}

sc_cobalt_kill绯荤粺璋冪敤,鍒欐槸閫氳繃pid鏉ユ壘鍒板搴旂殑cobalt_thread,鐒跺悗璋冪敤__cobalt_kill()銆?code>sc_cobalt_thread_kill绯荤粺璋冪敤鍐咃紝灏唒thread_t浣滀负hashkey锛屾壘鍒拌绾跨▼鐨刢obalt_thread锛屾渶缁堣皟鐢?code>__cobalt_kill()銆?/p>

涓嶅悓鐨勬槸璋冪敤__cobalt_kill鐨勭涓変釜鍙傛暟銆?code>sc_cobalt_kill绯荤粺璋冪敤浼犲叆鐨勬槸1锛岃〃绀虹粰绾跨▼缁勫彂閫佷俊鍙凤紝褰搕hread鎸囧悜鐨勯偅涓嚎绋嬫病鏈夌瓑寰呬换浣曚俊鍙锋椂浼氬皾璇曞彂閫佺粰鍚屼竴绾跨▼缁勫叾浠栫瓑寰呰淇″彿鐨勭嚎绋嬶紱sc_cobalt_thread_kill绯荤粺璋冪敤鍐呬紶鍏ョ殑鏄?.褰搕hread鎸囧悜鐨勯偅涓嚎绋嬫病鏈夌瓑寰呬换浣曚俊鍙锋椂灏变笉鍋氫换浣曟搷浣滅洿鎺ヨ繑鍥炪€?/p>

int __cobalt_kill(struct cobalt_thread *thread, int sig, int group) /* nklocked, IRQs off */
{
	struct cobalt_sigpending *sigp;
	int ret = 0;
	switch(sig) {
	case 0:
		/* Check for existence only. */
		break;
	case SIGSUSP:
		xnthread_suspend(&thread->threadbase, XNSUSP,
				 XN_INFINITE, XN_RELATIVE, NULL);
		if (&thread->threadbase == xnthread_current() &&
		    xnthread_test_info(&thread->threadbase, XNBREAK))
			ret = -EINTR;
		break;
	case SIGRESM:
		xnthread_resume(&thread->threadbase, XNSUSP);
		goto resched;
	case SIGRELS:
		xnthread_unblock(&thread->threadbase);
		goto resched;
	case SIGKICK:
		xnthread_kick(&thread->threadbase);
		goto resched;
	case SIGDEMT:
		xnthread_demote(&thread->threadbase);
		goto resched;
	case 1 ... _NSIG:
		sigp = cobalt_signal_alloc();  /*鍒嗛厤涓€涓俊鍙风粨鏋勪綋*/
		if (sigp) {
			sigp->si.si_signo = sig;
			sigp->si.si_errno = 0;
			sigp->si.si_code = SI_USER;
			sigp->si.si_pid = task_pid_nr(current);
			sigp->si.si_uid = get_current_uuid();
			if (cobalt_signal_send(thread, sigp, group) <= 0)
				cobalt_signal_free(sigp);
		}
	resched:
		xnsched_run();
		break;
	default:
		ret = -EINVAL;
	}

	return ret;
}

xenomai鍐呮牳涓璓OSIX淇″彿鏀寔鎺掗槦锛屽厛鍒嗛厤涓€涓猚obalt_sigpending銆傜洿鎺ュ垎閰嶇粨鏋勪綋澶у皬鐨勫唴瀛樻槸涓嶅彲鍙栫殑锛岃繖浼氬奖鍝嶅疄鏃舵€э紝xenomai閲囧彇鐨勫姙娉曟槸鍜寈nobject绫讳技锛屼笉閫氳繃鍔ㄦ€佸唴瀛樺垎閰嶏紝鍐呮牳鍒濆鍖栫殑鏃跺€欏氨鐢宠濂?code>_NSIG + (SIGRTMAX - SIGRTMIN) * 2涓猚obalt_sigpending鐨勫唴瀛榮igpending_mem锛岀劧鍚庡皢杩欎竴涓釜cobalt_sigpending绌垮埌閾捐〃sigpending_pool銆俢obalt_signal_alloc()灏辨槸鐩存帴浠庨摼琛╯igpending_pool涓婂彇涓€涓氨鍙互锛宑obalt_signal_free閲婃斁鏃跺啀鍔犲叆閾捐〃sigpending_pool銆?/p>

鎶€鏈浘鐗? src=

__SIGPOOL_SIZE澶у皬,涓哄湪kernelxenomaiposixsignal.c瀹氫箟濡備笅锛?/p>

#define __SIGPOOL_SIZE  (sizeof(struct cobalt_sigpending) *				 (_NSIG + (SIGRTMAX - SIGRTMIN) * 2))

娉ㄦ剰锛氳繖璇存槑鏁翠釜xenomai绯荤粺鍐呭彧鏈?4涓猚obalt_sigpending锛岃繖鎰忓懗濡傛灉婊ョ敤xenomai淇″彿锛屾垨闅忔剰鍚戝叾浠杧enomai绾跨▼鍙戦€?gt;31鍙风殑淇″彿锛岃€岃繖涓嚎绋嬫病鏈夎皟鐢╯igwait鐨勬搷浣滐紝閭d箞杩欎簺cobalt_sigpending浼氳姘歌繙鐨勬帓闃熷湪杩欎釜绾跨▼涓婏紝鐩村埌绾跨▼A閫€鍑烘墠浼氳閲婃斁銆傝繖浼氬鑷碿obalt_sigpending鏋锛岃繘鑰屽奖鍝嶅叾浠栦娇鐢ㄤ俊鍙风殑绋嬪簭鏃犳硶姝e父宸ヤ綔銆?/strong>

涓婇潰鐨刢obalt_signal_alloc()鏄笉鏄疊UG锛熸病鏈塩obalt_signal_alloc()鍒嗛厤澶辫触鐨勫鐞嗛€昏緫銆傝繖鏍峰簲鐢ㄦ棤娉曠煡閬撴槸鍚﹀彂閫佹垚鍔熶簡銆?/mark>璁剧疆cobalt_sigpending鐨勪俊鍙风紪鍙穝i.si_signo锛屼俊鍙风被鍨媠i.si_code锛屽彂閫佽€呮槸璋乻i.si_pid锛屽彂閫佽€呯殑uid澶氬皯si.si_uid銆備娇鐢╟obalt_signal_send杩涜鍙戦€併€?/p>

涓嬮潰鐪嬪彂閫佸嚱鏁癱obalt_signal_send銆?/p>

int cobalt_signal_send(struct cobalt_thread *thread,
		       struct cobalt_sigpending *sigp,
		       int group)
{				/* nklocked, IRQs off */
	struct list_head *sigq;
	int sig, ret;
	/* Can we deliver this signal immediately?*/
	ret = cobalt_signal_deliver(thread, sigp, group);
	if (ret)
		return ret;	/* Yep, done. */

	......
	sig = sigp->si.si_signo;
	sigq = thread->sigqueues + sig - 1;
	if (!list_empty(sigq)) {
		/* Queue non-rt signals only once. */
		if (sig < SIGRTMIN)
			return 0;
		/* Queue rt signal source only once (SI_TIMER). */
		if (!list_empty(&sigp->next))
			return 0;
	}

	sigaddset(&thread->sigpending, sig);
	list_add_tail(&sigp->next, sigq); 

	return 1;
}

鎴戜滑鍙戦€佷俊鍙风粰鐨勮繖涓嚎绋嬶紝鏈夊彲鑳芥鍦ㄩ樆濉炵瓑寰呬俊鍙凤紝鍏堣皟鐢╟obalt_signal_deliver鐪嬪畠鏄笉鏄湪绛夊緟锛屾槸鐨勮瘽鐩存帴灏遍€掗€?deliver)浜?

濡傛灉涓嶈兘鍙婃椂閫掗€?鍐嶅皢杩欎釜淇″彿鎸傝捣锛屼互涓嬩袱绫讳俊鍙蜂笉鏀寔鎺掗槦锛?.瀵逛簬灏忎簬SIGRTMIN(32)鐨勪俊鍙凤紝涓嶆敮鎸佹帓闃燂紝鍙寕璧蜂竴娆°€?.濡傛灉鍙戦€佹潵鐨剆igp鏄涓猄I_TIMER淇″彿锛堝畾鏃跺櫒鍒版湡淇″彿锛夛紝涔熷彧鎺掗槦涓€娆★紙涓巐inux澶勭悊鏂瑰紡涓€鑷达紝搴旇鏄痯osix鏍囧噯锛夈€傛帓闃熷氨鏄皢杩欎釜cobalt_sigpending鎻掑叆thread->sigqueues[signo-1]閾捐〃灏俱€?/p>

鎺掗槦鐨勪俊鍙锋槸涓嶄細琚唴鏍稿鐞嗙殑锛岀洿鍒扮敤璋冪敤sigwaitinfo銆乻igwait銆乻igtimedwait鏉ユ秷鑰椾粬浠€?/p>

static int cobalt_signal_deliver(struct cobalt_thread *thread,
				 struct cobalt_sigpending *sigp,
				 int group)
{				/* nklocked, IRQs off */
	struct cobalt_sigwait_context *swc;
	struct xnthread_wait_context *wc;
	int sig, ret;

	sig = sigp->si.si_signo;
	XENO_BUG_ON(COBALT, sig < 1 || sig > _NSIG);

	if (xnsynch_pended_p(&thread->sigwait)) {  
		wc = xnthread_get_wait_context(&thread->threadbase);
		swc = container_of(wc, struct cobalt_sigwait_context, wc);
		if (sigismember(swc->set, sig))
			goto deliver;
	}

	/*
	 * If that does not work out and we are sending to a thread
	 * group, try to deliver to any thread from the same process
	 * waiting for that signal.
	 */
	if (!group || list_empty(&thread->process->sigwaiters))
		return 0;

	list_for_each_entry(thread, &thread->process->sigwaiters, signext) {
		wc = xnthread_get_wait_context(&thread->threadbase);
		swc = container_of(wc, struct cobalt_sigwait_context, wc);
		if (sigismember(swc->set, sig))
			goto deliver;
	}

	return 0;
deliver:
	cobalt_copy_siginfo(sigp->si.si_code, swc->si, &sigp->si);
	.....
	xnthread_complete_wait(&swc->wc);
	xnsynch_wakeup_one_sleeper(&thread->sigwait);  /*鍞ら啋绾跨▼*/
	list_del(&thread->signext);

	cobalt_signal_free(sigp);

	return 1;
}
  1. 鍏堢湅杩欎釜绾跨▼鏄惁姝e湪绛夊緟淇″彿锛屽苟涓旂瓑寰呯殑淇″彿闆嗕腑鍖呭惈鎴戜滑鍙戦€佺殑杩欎釜淇″彿锛屽氨鐩存帴閫掗€?/li>
  2. 鍚﹀垯鐨勮瘽鐪嬭繖涓俊鍙锋槸閫氳繃kill杩樻槸pthread_kill鍙戦€佺殑锛屽鏋滄槸kill锛坓roup 绛変簬1锛夊氨鍦ㄧ湅鐪嬬嚎绋嬬粍鍐呮湁娌℃湁鍏朵粬涓嬬嚎绋嬬瓑寰呰繖涓俊鍙枫€傚惁鍒欑殑璇濋€掗€佷笉鎴愬姛杩斿洖0锛屽洖鍒癱obalt_signal_send灏嗚繖涓俊鍙锋寕璧锋帓闃熴€?/li>
  3. 閫掗€佽繃绋嬪緢绠€鍗曪紝xenomai绾跨▼绛夊緟淇″彿鐨勬椂鍊欎笉鏄樆濉炲湪sigwait涓婂悧锛岀洿鎺ュ敜閱掑畠锛屽憡璇夊畠鍝釜淇″彿鏉ヤ簡灏辫浜嗭紝鎺ョ潃閲婃斁鍙戦€佹椂鍒嗛厤鐨刢obalt_sigpending銆?/li>

2.2 xenomai鎺ユ敹澶勭悊淇″彿

绾跨▼璋冪敤sigwaitinfo()銆?code>sigtimedwait()鍜?code>sigwait()鏉ユ帴鏀朵俊鍙凤紝閮芥槸posix鏍囧噯锛屼綔鐢ㄤ笌linux绾跨▼涓€鑷淬€傚悓鏍凤紝缂栬瘧鏃朵細閾炬帴鍒發ibcobalt锛屽啀鐢眑ibcobalt鍙戣捣绯荤粺璋冪敤銆?/p>

COBALT_IMPL(int, sigwait, (const sigset_t *set, int *sig))
{
	int ret, oldtype;
    
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
	ret = -XENOMAI_SYSCALL2(sc_cobalt_sigwait, set, sig);
	pthread_setcanceltype(oldtype, NULL);
	return ret;
}
COBALT_IMPL(int, sigwaitinfo, (const sigset_t *set, siginfo_t *si))
{
	int ret, oldtype;

	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

	ret = XENOMAI_SYSCALL2(sc_cobalt_sigwaitinfo, set, si);
	.....
	pthread_setcanceltype(oldtype, NULL);

	return ret;
}

COBALT_IMPL(int, sigtimedwait, (const sigset_t *set, siginfo_t *si,
				const struct timespec *timeout))
{
	int ret, oldtype;
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);

	ret = XENOMAI_SYSCALL3(sc_cobalt_sigtimedwait, set, si, timeout);
	......
	pthread_setcanceltype(oldtype, NULL);

	return ret;
}

鍙戣捣绯荤粺璋冪敤杩涘叆xenomai鍐呮牳鍚庢渶缁堥兘鏄墽琛宻ignal_wait()銆?/p>

static int signal_wait(sigset_t *set, xnticks_t timeout,
		       void __user *u_si,
		       int (*put_siginfo)(void __user *u_si,
					  const struct siginfo *si,
					  int overrun))
{
	struct cobalt_sigpending *sigp = NULL;
	struct cobalt_sigwait_context swc;
	struct cobalt_thread *curr;
	int ret, sig, n, overrun;
	unsigned long *p, *t, m;
	struct siginfo si, *sip;
	struct list_head *sigq;
	spl_t s;

	curr = cobalt_current_thread();

check:
	if (sigisemptyset(&curr->sigpending)) 
		goto wait;

	p = curr->sigpending.sig; /* pending */
	t = set->sig;		  /* tested */

	for (n = 0, sig = 0; n < _NSIG_WORDS; ++n) {
		m = *p++ & *t++;
		if (m == 0)
			continue;
		sig = ffz(~m) +  n *_NSIG_BPW + 1;
		break;
	}

	if (sig) {
		sigq = curr->sigqueues + sig - 1;  
		......
		sigp = list_get_entry(sigq, struct cobalt_sigpending, next);
		INIT_LIST_HEAD(&sigp->next); /* Mark sigp as unlinked. */
		if (list_empty(sigq))
			sigdelset(&curr->sigpending, sig);
		sip = &sigp->si;
		ret = 0;
		goto done;
	}

wait:
	if (timeout == XN_NONBLOCK) {
		ret = -EAGAIN;
		goto fail;
	}
	swc.set = set;
	swc.si = &si;
	xnthread_prepare_wait(&swc.wc);
	list_add_tail(&curr->signext, &curr->process->sigwaiters);
	ret = xnsynch_sleep_on(&curr->sigwait, timeout, XN_RELATIVE);
	.......
	sig = si.si_signo;
	sip = &si;
done:
	switch (sip->si_code) {
	case SI_TIMER:	
		overrun = cobalt_timer_deliver(sip->si_tid);
		break;
	case SI_USER:
	case SI_MESGQ:
	case SI_QUEUE:
		overrun = 0;
		break;
	default:
		overrun = sip->si_overrun;
		if (overrun)
			sip->si_overrun = 0;
	}
    
	if (u_si == NULL)
		goto out;	/* Return signo only. */

	ret = put_siginfo(u_si, sip, overrun);// signal_put_siginfo
	if (ret)
		goto out;
	......
out:
	.....
	if (sigp &&
	    (void *)sigp >= sigpending_mem &&
	    (void *)sigp < sigpending_mem + __SIGPOOL_SIZE) {
		xnlock_get_irqsave(&nklock, s);
		list_add_tail(&sigp->next, &sigpending_pool);
		xnlock_put_irqrestore(&nklock, s);
		/* no more ref. to sigp beyond this point. */
	}
	return ret ?: sig;
fail:

	return ret;
}
  1. 鍏堟鏌urr->sigpending 鏄惁鏈夋湭鍐崇殑淇″彿锛屽鏋滄湁鐨勮瘽灏辩洿鎺ヨ烦杞埌鏍囩done澶勭悊銆?/li>
  2. 鍚﹀垯寰€涓嬭繘鍏ait鏍囩,鐫$湢鍒癱urr->sigwait銆傜洿鍒拌秴鏃舵垨绛夊緟鐨勪俊鍙峰埌鏉ユ墠浼氱户缁線涓嬫墽琛宒one鎿嶄綔銆?/li>
  3. done涓鐞嗕竴涓媡imer瓒呮湡淇″彿锛屽鏋滈渶瑕佹嫹璐漵ifinfo锛屽垯璋冪敤put_siginfo鎷疯礉涓€涓嬨€?/li>
  4. 鎵цout鎿嶄綔閲婃斁绛夊緟鍒扮殑cobalt_sigpending銆?/li>

3 鍙屾牳淇″彿鎬荤粨

  • 涓ょ淇″彿锛歺enomai淇″彿鍜宭inux淇″彿銆?/p>

  • 鐞嗘竻鍙屾牳涓嬬殑淇″彿闇€瑕佸垎娓咃細Linux杩涚▼涓庣嚎绋嬨€亁enomai绾跨▼涓夎€呬箣闂寸殑鍏崇郴鍙婁綔鐢ㄥ煙銆?/p>

  • linux鐨勮繘绋嬩笌绾跨▼閮芥湁淇″彿灞忚斀闆嗭紝xenomai淇″彿鍒欐病鏈夈€?/p>

  • 鍙屾牳搴旂敤浠g爜涓娇鐢ㄥ嚱鏁板彂閫乴inux淇″彿鏃讹紝鏈€濂戒娇鐢?code>__STD()淇グ淇″彿鐩稿叧鍑芥暟銆?/p>

  • 濡傛灉涓嶆樉寮忚皟鐢ㄦ帴鍙?code>sigwaitinfo()銆?code>sigtimedwait()鍜?code>sigwait()鏉ユ帴鏀朵俊鍙峰鐞唜enomai淇″彿锛岄偅涔堟案杩滀笉浼氬緱鍒板鐞嗐€傛墍浠ヤ笉鑳芥互鐢▁enomai淇″彿锛屽洜涓轰俊鍙锋湁闄愩€?/p>

  • xenomai鍐呮牳灏嗕俊鍙蜂綔涓轰竴绉嶅悓姝ヨ祫婧愶紙xnsynch锛夋潵绠$悊锛岀煡閬撹繖涓€鐐癸紝骞剁悊瑙d簡13.2 璧勬簮鍚屾瀵硅薄鈥攛nsynch宸ヤ綔鍘熺悊锛屽氨鐭ラ亾xenomai淇″彿濡備綍宸ヤ綔銆?/p>

鏈枃涓烘湰鏂囦负鍗氫富鍘熷垱鏂囩珷锛岃浆杞借娉ㄦ槑鍑哄銆傚鏈夐敊璇紝娆㈣繋鎸囨銆傚崥瀹㈠湴鍧€锛?a href="https://www.cnblogs.com/wsg1100/">https://www.cnblogs.com/wsg1100/

以上是关于xenomai鍐呮牳瑙f瀽涔嬩俊鍙穝ignal(浜?---xenomai淇″彿澶勭悊鏈哄埗的主要内容,如果未能解决你的问题,请参考以下文章

璧垫櫒闆細浠庢枃浠剁郴缁熺殑鏁版嵁缁撴瀯鐪婰inux鍐呮牳璁捐

HTTP/2鍐呮牳鍓栨瀽

NT 鍐呮牳鍑芥暟鍘熷瀷澶у叏

Linux鍔ㄦ€佷负鍐呮牳娣诲姞鏂扮殑绯荤粺璋冪敤

鎿嶄綔绯荤粺-鎿嶄綔绯荤粺-鍐呮牳涓殑灞忓箷鎵撳嵃(涓?

鏋勫缓璋冭瘯Linux鍐呮牳缃戠粶浠g爜鐨勭幆澧僊enuOS绯荤粺