setcontext - setcontext
setcontext bir ailemdendir Cı kütüphane fonksiyonları (diğerleri getContext , makecontext ve swapcontext için kullanılır) bağlamı kontrol. setcontext Aile gelişmiş C kullanım imkanı sağlayan denetim akışı desenleri gibi iterators , lifler ve değiş tokuş eden kavramlar . Setjmp / longjmp'nin gelişmiş bir sürümü olarak görülebilirler ; ikinci kadar sadece tek bir yerel olmayan sıçrama mümkündür, öte yandan yığını , setcontext birden fazla oluşturulmasını sağlar kooperatif kontrol iplikleri , kendi yığın her biri.
Şartname
setcontext belirtildi POSIX'deki ,1-2.001 ve Tek Unix Şartname , sürüm 2, ancak tüm Unix benzeri işletim sistemleri bunları sağlamak. POSIX .1-2004 bu işlevleri geçersiz kıldı ve POSIX .1-2008'de kaldırıldılar, POSIX Konuları olası bir yedek olarak belirtildi. IEEE Std 1003.1, 2004 Baskısından alıntı:
ISO / IEC 9899: 1999 standardının bu spesifikasyona dahil edilmesiyle, ISO C standardının (Alt Madde 6.11.6) boş parantezli fonksiyon tanımlayıcıların kullanımının eskimiş bir özellik olduğunu belirttiği bulunmuştur. Bu nedenle, işlev prototipini kullanarak:
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);ISO C standardının eskimiş bir özelliğini kullanıyor. Bu nedenle, kesinlikle uyumlu bir POSIX uygulaması bu formu kullanamaz. Bu nedenle getcontext (), makecontext () ve swapcontext () kullanımları eskimiş olarak işaretlenmiştir.
ISO C standardında, bir işlevin rastgele türde argümanların (tamsayılar, verilere işaretçiler, işlevlere işaretçiler dahil) keyfi sayıda (sıfır dahil) ile çağrılacağını belirten eskimeyen bir işlev prototipi belirtmenin bir yolu yoktur. bileşik türler).
Tanımlar
İşlevler ve ilişkili türler, ucontext.h sistem başlık dosyasında tanımlanır . Bu, ucontext_t dört işlevin tümünün çalıştığı türü içerir :
typedef struct {
ucontext_t *uc_link;
sigset_t uc_sigmask;
stack_t uc_stack;
mcontext_t uc_mcontext;
...
} ucontext_t;
uc_link bağlam makecontext (ikincil bir bağlam) ile oluşturulmuşsa, geçerli bağlam çıktığında devam ettirilecek bağlama işaret eder . uc_sigmask dizisini depolamak üzere kullanılır sinyalleri bağlamında engellenir ve uc_stack bir yığın bağlamda kullanılan. tüm yazmaçlar ve CPU bayrakları , talimat işaretçisi ve yığın işaretçisi dahil olmak üzere yürütme durumunuuc_mcontext depolar ; Bir olan opak türü .
mcontext_t
İşlevler şunlardır:
-
int setcontext(const ucontext_t *ucp)- Bu işlev, denetimi içindeki içeriğe aktarır
ucp. Yürütme, bağlamın depolandığı noktadan itibaren devam ederucp.setcontextgeri dönmez.
- Bu işlev, denetimi içindeki içeriğe aktarır
-
int getcontext(ucontext_t *ucp)- Geçerli bağlamı içine kaydeder
ucp. Bu işlev iki olası durumda geri döner: ilk çağrıdan sonra veya bir iş parçacığı veyaucparacılığıyla bağlama geçtiğinde . Fonksiyon sağlamaz dönüş değeri programcı bir kayıt değişken olmamalıdır açık bir bayrak değişken kullanmalıdır ve beyan edilmelidir, böylece (dönüş değeri sinyal hatası amacıyla kullanılan,) vakaları ayırt uçucu önlemek için sürekli yayılma veya diğer derleyici optimizasyonları .setcontextswapcontextgetcontext
- Geçerli bağlamı içine kaydeder
-
void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...)makecontextFonksiyon kontrol alternatif bir iplik kurarucpönceden kullanılarak başlatıldı edilmişgetcontext.ucp.uc_stackElemanı uygun büyüklükte bir yığının işaret edilmelidir; sabitSIGSTKSZyaygın olarak kullanılır. Ne zamanucpkullanarak atladı edilirsetcontextyaswapcontext, yürütme başlayacak giriş noktasına işaret ettiği fonksiyonafuncsahip,argcbelirtilen argümanlar. Ne zamanfuncsona erer, kontrol döndürülürucp.uc_link.
-
int swapcontext(ucontext_t *oucp, ucontext_t *ucp)- Denetimi
ucpaktarır ve geçerli yürütme durumunu içine kaydederoucp.
- Denetimi
Misal
Aşağıdaki örnek setcontext ,.
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
/* The three contexts:
* (1) main_context1 : The point in main to which loop will return.
* (2) main_context2 : The point in main to which control from loop will
* flow by switching contexts.
* (3) loop_context : The point in loop to which control from main will
* flow by switching contexts. */
ucontext_t main_context1, main_context2, loop_context;
/* The iterator return value. */
volatile int i_from_iterator;
/* This is the iterator function. It is entered on the first call to
* swapcontext, and loops from 0 to 9. Each value is saved in i_from_iterator,
* and then swapcontext used to return to the main loop. The main loop prints
* the value and calls swapcontext to swap back into the function. When the end
* of the loop is reached, the function exits, and execution switches to the
* context pointed to by main_context1. */
void loop(
ucontext_t *loop_context,
ucontext_t *other_context,
int *i_from_iterator)
{
int i;
for (i=0; i < 10; ++i) {
/* Write the loop counter into the iterator return location. */
*i_from_iterator = i;
/* Save the loop context (this point in the code) into ''loop_context'',
* and switch to other_context. */
swapcontext(loop_context, other_context);
}
/* The function falls through to the calling context with an implicit
* ''setcontext(&loop_context->uc_link);'' */
}
int main(void)
{
/* The stack for the iterator function. */
char iterator_stack[SIGSTKSZ];
/* Flag indicating that the iterator has completed. */
volatile int iterator_finished;
getcontext(&loop_context);
/* Initialise the iterator context. uc_link points to main_context1, the
* point to return to when the iterator finishes. */
loop_context.uc_link = &main_context1;
loop_context.uc_stack.ss_sp = iterator_stack;
loop_context.uc_stack.ss_size = sizeof(iterator_stack);
/* Fill in loop_context so that it makes swapcontext start loop. The
* (void (*)(void)) typecast is to avoid a compiler warning but it is
* not relevant to the behaviour of the function. */
makecontext(&loop_context, (void (*)(void)) loop,
3, &loop_context, &main_context2, &i_from_iterator);
/* Clear the finished flag. */
iterator_finished = 0;
/* Save the current context into main_context1. When loop is finished,
* control flow will return to this point. */
getcontext(&main_context1);
if (!iterator_finished) {
/* Set iterator_finished so that when the previous getcontext is
* returned to via uc_link, the above if condition is false and the
* iterator is not restarted. */
iterator_finished = 1;
while (1) {
/* Save this point into main_context2 and switch into the iterator.
* The first call will begin loop. Subsequent calls will switch to
* the swapcontext in loop. */
swapcontext(&main_context2, &loop_context);
printf("%d\n", i_from_iterator);
}
}
return 0;
}
NOT: Bu örnek doğru değildir, ancak bazı durumlarda amaçlandığı gibi çalışabilir. İşlev makecontext , tür olması için ek parametreler gerektirir int , ancak örnek işaretçilerden geçer. Bu nedenle, örnek 64 bit makinelerde (özellikle LP64 mimarilerinde ) başarısız olabilir . Bu sorun 64 bitlik değerlerin parçalanması ve yeniden yapılandırılmasıyla çözülebilir, ancak bu bir performans cezası getirir.
sizeof(void*) > sizeof(int)
İnt ve işaretçi türlerinin aynı boyutta olduğu mimarilerde (örneğin, her iki türün de 32 bit olduğu x86-32), argc'yi takiben makecontext () için işaretçileri argüman olarak iletmekten kurtulabilirsiniz. Ancak, bunun taşınabilir olması garanti edilmez, standartlara göre tanımlanmamıştır ve işaretçilerin inçlerden daha büyük olduğu mimarilerde çalışmayacaktır. Bununla birlikte, 2.8 sürümünden başlayarak glibc,
, bazı 64 bit mimarilerde buna izin vermek için (örneğin, x86-64).
İçeriği almak ve ayarlamak için daha küçük bir bağlam kullanışlı olabilir:
#include <stdio.h>
#include <ucontext.h>
#include <unistd.h>
int main(int argc, const char *argv[]){
ucontext_t context;
getcontext(&context);
puts("Hello world");
sleep(1);
setcontext(&context);
return 0;
}
Bu, sonsuz bir döngü oluşturur çünkü bağlam, program sayacını tutar.
Referanslar
Dış bağlantılar
- System V Contexts - GNU C Kitaplığı Kılavuzu
- : mevcut kullanıcı bağlamını al / ayarla - Linux Programcı Kılavuzu - Kitaplık İşlevleri
- setcontext - mevcut kullanıcı bağlamı FreeBSD kılavuz sayfasını alır / ayarlar .