⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 notes.html

📁 快速开发
💻 HTML
📖 第 1 页 / 共 2 页
字号:
non thread-safe functions (in a traditional sense) can be safely used withthe State Threads.  The library's mutex facilities are practically uselessfor a correctly written application (no blocking functions in criticalsection) and are provided mostly for completeness.  This absence of lockinggreatly simplifies an application design and provides a foundation forscalability.<P><A NAME="inter"><H3>Inter-Process Synchronization</H3>The State Threads library makes it possible to multiplex a large numberof simultaneous connections onto a much smaller number of separate processes, where each process uses a many-to-one user-level threadingimplementation (<B>N</B> of <B>M:1</B> mappings rather than one <B>M:N</B>mapping used in native threading libraries on some platforms). This designis key to the application's scalability.  One can think about it as if aset of all threads is partitioned into separate groups (processes) whereeach group has a separate pool of resources (virtual address space, filedescriptors, etc.).  An application designer has full control of how manygroups (processes) an application creates and what resources, if any,are shared among different groups via standard UNIX inter-processcommunication (IPC) facilities.<P>There are several reasons for creating multiple processes:<P><UL><LI>To take advantage of multiple hardware entities (CPUs, disks, etc.)available in the system (hardware parallelism).</LI><P><LI>To reduce risk of losing a large number of user connections when one ofthe processes crashes. For example, if <B>C</B> user connections (threads)are multiplexed onto <B>P</B> processes and one of the processes crashes,only a fraction (<B>C/P</B>) of all connections will be lost.</LI><P><LI>To overcome per-process resource limitations imposed by the OS.  Forexample, if <TT>select(2)</TT> is used for event polling, the number ofsimultaneous connections (threads) per process islimited by the <TT>FD_SETSIZE</TT> parameter (see <TT>select(2)</TT>).If <TT>FD_SETSIZE</TT> is equal to 1024 and each connection needs one filedescriptor, then an application should create 10 processes to support 10,000simultaneous connections.</LI></UL><P>Ideally all user sessions are completely independent, so there is no need forinter-process communication.  It is always better to have several separatesmaller process-specific resources (e.g., data caches) than to have one largeresource shared (and modified) by all processes.  Sometimes, however, thereis a need to share a common resource among different processes.  In that case,standard UNIX IPC facilities can be used.  In addition to that, there is a wayto synchronize different processes so that only the thread accessing theshared resource will be suspended (but not the entire process) if that resourceis unavailable.  In the following code fragment a pipe is used as a countingsemaphore for inter-process synchronization:<PRE>#ifndef PIPE_BUF#define PIPE_BUF 512  /* POSIX */#endif/* Semaphore data structure */typedef struct ipc_sem {  st_netfd_t rdfd;  /* read descriptor */  st_netfd_t wrfd;  /* write descriptor */} ipc_sem_t;/* Create and initialize the semaphore. Should be called before fork(2). *//* 'value' must be less than PIPE_BUF. *//* If 'value' is 1, the semaphore works as mutex. */ipc_sem_t *ipc_sem_create(int value){  ipc_sem_t *sem;  int p[2];  char b[PIPE_BUF];  /* Error checking is omitted for clarity */  sem = malloc(sizeof(ipc_sem_t));  /* Create the pipe */  pipe(p);  sem->rdfd = st_netfd_open(p[0]);  sem->wrfd = st_netfd_open(p[1]);  /* Initialize the semaphore: put 'value' bytes into the pipe */  write(p[1], b, value);  return sem;}/* Try to decrement the "value" of the semaphore. *//* If "value" is 0, the calling thread blocks on the semaphore. */int ipc_sem_wait(ipc_sem_t *sem){  char c;  /* Read one byte from the pipe */  if (st_read(sem->rdfd, &c, 1, ST_UTIME_NO_TIMEOUT) != 1)    return -1;  return 0;}/* Increment the "value" of the semaphore. */int ipc_sem_post(ipc_sem_t *sem){  char c;  if (st_write(sem->wrfd, &c, 1, ST_UTIME_NO_TIMEOUT) != 1)    return -1;  return 0;}</PRE><P>Generally, the following steps should be followed when writing an applicationusing the State Threads library:<P><OL><LI>Initialize the library (<TT>st_init()</TT>).</LI><P><LI>Create resources that will be shared among different processes:    create and bind listening sockets, create shared memory segments, IPC    channels, synchronization primitives, etc.</LI><P><LI>Create several processes (<TT>fork(2)</TT>). The parent process should    either exit or become a "watchdog" (e.g., it starts a new process when    an existing one crashes, does a cleanup upon application termination,    etc.).</LI><P><LI>In each child process create a pool of threads    (<TT>st_thread_create()</TT>) to handle user connections.</LI></OL><P><A NAME="nonnet"><H3>Non-Network I/O</H3>The State Threads architecture uses non-blocking I/O on<TT>st_netfd_t</TT> objects for concurrent processing of multiple userconnections.  This architecture has a drawback:  the entire process andall its threads may block for the duration of a <I>disk</I> or othernon-network I/O operation, whether through State Threads I/O functions,direct system calls, or standard I/O functions.  (This is applicablemostly to disk <I>reads</I>; disk <I>writes</I> are usually performedasynchronously -- data goes to the buffer cache to be written to disklater.)  Fortunately, disk I/O (unlike network I/O) usually takes afinite and predictable amount of time, but this may not be true forspecial devices or user input devices (including stdin).  Nevertheless,such I/O reduces throughput of the system and increases response times.There are several ways to design an application to overcome thisdrawback:<P><UL><LI>Create several identical main processes as described above (symmetric    architecture).  This will improve CPU utilization and thus improve the    overall throughput of the system.</LI><P><LI>Create multiple "helper" processes in addition to the main process that    will handle blocking I/O operations (asymmetric architecture).    This approach was suggested for Web servers in a    <A HREF="http://www.cs.rice.edu/~vivek/flash99/">paper</A> by Peter    Druschel et al. In this architecture the main process communicates with    a helper process via an IPC channel (<TT>pipe(2), socketpair(2)</TT>).    The main process instructs a helper to perform the potentially blocking    operation.  Once the operation completes, the helper returns a    notification via IPC.</UL><P><A NAME="timeouts"><H3>Timeouts</H3>The <TT>timeout</TT> parameter to <TT>st_cond_timedwait()</TT> and theI/O functions, and the arguments to <TT>st_sleep()</TT> and<TT>st_usleep()</TT> specify a maximum time to wait <I>since the lastcontext switch</I> not since the beginning of the function call.<P>The State Threads' time resolution is actually the time intervalbetween context switches.  That time interval may be large in somesituations, for example, when a single thread does a lot of workcontinuously.  Note that a steady, uninterrupted stream of network I/Oqualifies for this description; a context switch occurs only when athread blocks.<P>If a specified I/O timeout is less than the time interval betweencontext switches the function may return with a timeout error beforethat amount of time has elapsed since the beginning of the functioncall.  For example, if eight milliseconds have passed since the lastcontext switch and an I/O function with a timeout of 10 millisecondsblocks, causing a switch, the call may return with a timeout error aslittle as two milliseconds after it was called.  (On Linux,<TT>select()</TT>'s timeout is an <I>upper</I> bound on the amount oftime elapsed before select returns.)  Similarly, if 12 ms have passedalready, the function may return immediately.<P>In almost all cases I/O timeouts should be used only for detecting abroken network connection or for preventing a peer from holding an idleconnection for too long.  Therefore for most applications realistic I/Otimeouts should be on the order of seconds.  Furthermore, there'sprobably no point in retrying operations that time out.  Rather thanretrying simply use a larger timeout in the first place.<P>The largest valid timeout value is platform-dependent and may besignificantly less than <TT>INT_MAX</TT> seconds for <TT>select()</TT>or <TT>INT_MAX</TT> milliseconds for <TT>poll()</TT>.  Generally, youshould not use timeouts exceeding several hours.  Use<tt>ST_UTIME_NO_TIMEOUT</tt> (<tt>-1</tt>) as a special value toindicate infinite timeout or indefinite sleep.  Use<tt>ST_UTIME_NO_WAIT</tt> (<tt>0</tt>) to indicate no waiting at all.<P><HR><P></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -