Diferencias entre el modelo de selección de Windows y Linux
Windows proporciona una variedad de modelos de E/S sin bloqueo, como selección, WSAAsyncSelect, WSAEventSelect, puertos de superposición y finalización, etc. Entre ellos, el puerto de finalización de IO (IOCP) proporciona mejores escalabilidad, más utilizado en Windows
Nota: el modelo se selecciona principalmente para resolver el problema de que solo se puede procesar un socket en modo de subproceso único, pero esto evita subprocesos inflados. Primero echemos un vistazo al prototipo y luego hablemos de las deficiencias.
Modo de selección: hay dos versiones principales de la biblioteca winsock Aquí tomamos principalmente la versión winsock2 como ejemplo para ilustrar el modelo de selección.
int select (int nfds , fd_set* readfds, fd_set* writefds, fd _set* exceptfds, const struct timeval* timeout);
De hecho, lo más importante es que estos Las dos versiones usan el mismo estándar, por lo que la interfaz es básicamente la misma que la de Linux. Lo mismo, pero nfds en realidad no tiene sentido en Windows. Esto se debe principalmente a la compatibilidad con otras versiones.
Procesamiento: se supone que se toma la lectura. Como ejemplo, aquí Windows agrega principalmente sockets a la colección readfds primero y luego espera a que regrese la función de selección. En la función de selección, los identificadores de socket que no tienen operaciones de E/S pendientes se eliminarán, es decir, el. El socket IO maneja que se han procesado y luego verifica si s está rechazado y todavía está en la colección readfs, luego verifica si s está rechazado o todavía está en la colección readfs, en cuyo caso s es legible, pero es legible y lo hace. no necesariamente tiene datos
Hay varias situaciones que desencadenarán esta situación: los datos son legibles, la conexión se cierra/reinicia/interrumpe, se llama al socket de escucha, todavía hay una conexión esperando ser procesada y la función de aceptación acepta con éxito el nuevo socket
Deficiencias: de hecho, existe un límite en la cantidad de sockets que se pueden agregar a fd_set, que winsock2.h define como 64. h, y el número de sockets que se pueden agregar a fd_set.
.h se define como 64 y la personalización no puede exceder 1024, porque este valor es demasiado grande y afectará el rendimiento del servidor. Los valores más altos son IOCP escalables
modelo de selección de Linux
.De hecho, el principio es similar al de Windows, pero existen algunas diferencias en el procesamiento subyacente
Modelo: int select (int maxfd, fd_set*readfds, fd_set* writefds, fd_set*exceptfds, const struct timeval*timeout) p>
Lo más importante aquí es maxfd, que es el rango de descriptores de archivos, que es 1 mayor que el descriptor de archivo más grande que se detectará
Proceso de procesamiento: el archivo monitoreado es también se agrega primero al conjunto de descriptores de archivos, llame al monitor de selección para determinar si el archivo ha cambiado, pero el método de encuesta se llama en la capa inferior primero use poll_wait para agregar la cola de espera a poll_table y devolver la máscara del descriptor; p>
prototipo de encuesta: unsigned int (* poll)(struct file *filp, poll_wait* wait)
Mire un proceso simple como este
unsigned int mem_poll(struct archivo *filp, poll_table *espera)
{
struct mem_dev *dev = filp-gt;
unsigned int mask = 0; >
/* Agregar cola de espera a poll_table */
poll_wait(filp, amp; dev- gt; inq, wait
if (have_data)
;máscara |= POLLIN | POLLRDNORM; / * Legible*/
return mask;
}
Aquí simplemente agregamos la cola y devolvemos un valor legible. y máscara grabable. El bloqueo real no está aquí, sino en la función do_select(...) en el kernel de Linux fs/select.
c
int do_select(int n, fd_set_bits *fds, struct timespec *end_time)
if (archivo) {
f_op = file-gt;
mask = DEFAULT_POLLMASK;
if (f_op amp; amp; f_op-gt; poll) {
wait_key_set(esperar, entrar, salir, bit);
mask = (*f_op- gt; poll) (archivo, espera
}
Aquí primero determinas si el archivo existe y luego lees); su propia función f_op definida para operar la E/S del dispositivo Hay una máscara predeterminada antes de determinar y devolver el descriptor máscara = (*f_op-gt; poll) (archivo, espere para distinguir cuál es la colección actual); activado; luego determine f_opamp; f_op-gt; poll. Aquí tenemos una función de sondeo definida de forma predeterminada, por lo que esta declaración de juicio se ingresará aquí, mask = (*f_op-gt; poll) (archivo, espere); Llamar a la función de sondeo predeterminada. La clave del procesamiento es ¿cómo distinguir entre diferentes procesos de lectura, escritura y excepción?
(maskamp;POLLIN_SET)amp;amp;(inamp;bit), que es el proceso actual de lectura, escritura y excepción, es para juzgar y distinguir si el socket actual es solo un fd_set específico. colección, por supuesto, un socket también puede ser legible y escribible al mismo tiempo, en cuyo caso se juzgarán ambos.
if (retval || timed_out || signal_pending(current))
break;
Si el retval anterior es 0 y otras condiciones insatisfechas provocarán el vacío estado de bucle, es decir, en estado bloqueado
Te sugiero que eches un vistazo a este método de aprendizaje en Linux. La dirección es 3w(dot)linuxprobe(dot)com. Te deseo buena suerte.
p>