Es posible cambiar la MANIJA que se ha abierto para el I/O, para ser abierto para asynchronous I/O durante su vida útil?

StackOverflow https://stackoverflow.com/questions/2475713

Pregunta

La mayor parte de mi diario de trabajo de programación en Windows es hoy en día alrededor de las operaciones de e/S de todo tipo (tuberías, consolas, archivos, sockets, ...).Soy muy consciente de los diferentes métodos de lectura y escritura de/a los diferentes tipos de controladores (Síncronos, asíncronos de espera para la finalización de los acontecimientos, a la espera de Identificadores de archivo de finalización de e/S puertos, y wait_alertable I/O).Utilizamos muchos de esos.

Para algunas de nuestras aplicaciones sería muy útil tener sólo una manera de tratar a todos los tiradores.Quiero decir, el programa no puede saber, qué tipo de mango que ha recibido y que le gustaría usar, digamos, finalización de e/S puertos para todos.

Así que primero me gustaría preguntar:

Supongamos que tengo un mango:

HANDLE h;

que se ha recibido por parte de mi proceso de I/O de algún lugar.¿Hay alguna forma sencilla y fiable para averiguar lo que la marca ha sido creada con el?El principal indicador en cuestión es FILE_FLAG_OVERLAPPED.

La única manera conocida para mí hasta ahora, es tratar de registrar este tipo de mango en finalización de e/S de puerto (el uso de CreateIoCompletionPort()).Si se realiza correctamente el mango ha sido creado con FILE_FLAG_OVERLAPPED.Pero, a continuación, sólo finalización de e/S de puerto que debe utilizarse, ya que el identificador no puede ser no registrados de ella sin cerrar el HANDLE h sí.

Si no es una fácil manera para determinar la presencia de FILE_FLAG_OVERLAPPED, no habría llegado a mi segunda pregunta:

Es allí cualquier manera de cómo agregar esa bandera a la ya existente de manejar?Eso haría que el mango ha sido originalmente abierto para operaciones síncronas de estar abierto a la asincrónica.¿Hay una manera de cómo crear opuesto (quitar el FILE_FLAG_OVERLAPPED para crear sincrónico de manejar desde el asincrónica)?

No he encontrado ninguna forma directa después de leer a través de MSDN y googlear un montón.Habrá, al menos, algún truco que podría hacer lo mismo?Como re-creación de la manija de la misma forma, el uso de CreateFile() función o algo similar?Algo, aunque sea parcialmente, documentados o no documentados en todo?

El principal lugar donde se iba a necesitar esto, es determinar la forma (o cambiar la forma de) proceso debe leer/escribir desde maneja enviada por aplicaciones de terceros.No podemos controlar cómo los productos de terceros a crear sus asas.

Queridos Windows gurús:ayuda por favor!

Con respecto

Martin

¿Fue útil?

Solución 2

3 años pasaron y Windows 8 ha sido liberado. Gracias a la regresión introducida en la aplicación de consola en Windows 8 que tiene que hacer algo sobre el problema que provocó esta pregunta. Así que finalmente he tratado de usar ReOpenFile) llamada de función (.

En una frase:. Para mis propósitos es inútil

La API ReOpenFile () se utiliza para “tomar un identificador de archivo existente y conseguir otro mango que tiene un conjunto diferente de derechos de acceso”. Al menos eso se dice en el artículo original .

I intentado utilizar El ReOpenFile () en el mango de entrada de consola:

  stdin_in = GetStdHandle(STD_INPUT_HANDLE);
  stdin_in_operlapped = ReOpenFile(stdin_in, GENERIC_READ | GENERIC_WRITE,
                                   FILE_SHARE_READ, FILE_FLAG_OVERLAPPED);
  if (stdin_in_operlapped ==  INVALID_HANDLE_VALUE)
    {
      my_debug("failed to ReOpen stdin handle with OVERLAPPED flag: %d", GetLastError());
      exit(1);
    }

Y lo que consigo es: Error 1168: “Elemento no encontrado”. “Gracias Microsoft”. Ni siquiera voy a tratar de usarlo para tuberías anónimos, ya que la documentación indica:

“asincrónicos (superpuestas) lectura y escritura no son compatibles con las tuberías anónimos. Esto significa que no puede utilizar las funciones ReadFileEx y WriteFileEx con tubos anónimos. Además, el parámetro lpOverlapped de ReadFile y WriteFile se ignora cuando se utilizan estas funciones con tubos de anónimos.”

, la gente, a todos por sus sugerencias. Cuando se lee desde la manija de forma asíncrona, uno tiene que estar preparado también por el hecho de que la operación se puede completar de forma sincrónica. Eso lo sé. La razón principal por la que estaba haciendo esta pregunta es:

cuando una lectura sincrónica se ha emitido en algunos objetos (por lo menos anónimo tuberías y entrada de la consola en Windows 8) a continuación, llamar CloseHandle () de otro hilo en el mismo mango, o bien fallar, o colgar, hasta que el ReadFile () completa; eso significa que va a colgar indefinidamente en muchos casos. Esa es la razón por la que quería reemplazar el mango sincrónica con asíncrona.

Ahora bien, es claro que simplemente no es posible en los sistemas operativos Windows para cancelar algunas operaciones de lectura en forma directa. Cuando se lee desde manijas síncronos, sólo hay que salir de la aplicación, incluso si ReadFile () todavía está leyendo un mango en un poco de hilo, ya que es simplemente imposible para despertar de manera fiable una operación de este tipo de lectura. En know ... En más reciente del sistema operativo, es posible cancelar la operación. Sin embargo, no hay manera de saber el tiempo el hilo está en la llamada ReadFile () ya o todavía no. Si ReadFile () no se llama sin embargo, entonces no se realiza ninguna operación para cancelar y lectura posterior se colgará. La única manera sería cerrar el mango, pero esa operación se cuelga o falla en algunos objetos y en algunos sistemas operativos. La única solución adecuada a esta es asíncrona I / O. Pero, como he mencionado al principio, nuestra aplicación se inicia mediante aplicaciones de terceros y no podemos obligar a todos ellos para crear canalizaciones con nombre siempre con pabellón conjunto superpuesto para la stdio.

Me estoy dando y va a aplicar cortes feos desagradables ... vamos a tener que seguir leyendo sin estructura OVERLAPPED de mangos que se han creado con la bandera OVERLAPPED, y fugas de asas y los hilos ....

Otros consejos

veo yo era un mal lector de MSDN: / I función totalmente perdido ReOpenFile() que se ha introducido probablemente tan pronto como en junio de 2003 en Windows Server 2003 (de acuerdo con la este artículo ). Para defenderme al menos un poco: Yo esperaría que la descripción CreateFile() para cruzar referencia a ReOpenFile() descripción. Hay una referencia en la página ReOpenFile() a CreateFile() página, pero no al revés.

Esta función parece permitir, precisamente, lo que necesito: la adición o eliminación de FILE_FLAG_OVELRAPPED a / de las manijas ya existentes mediante la creación de nuevo mango con propiedades deseadas! :-D No he probado todavía, sin embargo. Es, por desgracia, sólo disponible en Windows Server 2003, Windows Vista y en adelante. Pregunta sobre las versiones anteriores del sistema operativo ha sido contestada aquí . La función no existe en la API pública en el sistema operativo anteriores a Windows Server 2003. Es utilizado por la implementación subyacente, pero no está disponible para los desarrolladores de estos sistemas (no soportado).

Esto significa prácticamente que no hay esperanza para mí, al menos para los próximos pocos años, hasta que se nos cae el apoyo a las plataformas anteriores de Windows. También significa que la situación con respecto a la E / S ha sido realmente malo en OS viejo entonces Windows Vista. Otra parte dolorosa que ha estado desaparecido por completo fue la posibilidad de cancelar sincrónica y asincrónica de E / S en los sistemas más antiguos.

Además, todavía echo de menos una parte de la respuesta: ¿puede la presencia de banderas ser probado por cualquier medio? No he encontrado la función por hacer eso. Eso significa que si queremos garantizar la presencia de algún indicador en objeto de archivo, el archivo siempre tiene que ser abierto de nuevo.

Si entiendo lo que está buscando, me gustaría sugerir que no le importa si se abrió con la bandera solapada o no. Creo que se puede pasar de forma segura en una estructura OVERLAPPED en los dos casos sincrónicos y asincrónicos. Su código debe ser capaz de manejar ReadFile() false regresar y volver GetLastError() ERROR_IO_PENDING. También tendrá que añadir las llamadas apropiadas a GetOverlappedResult(), WaitForSingleObject(), etc.

El artículo de MSDN sobre ReadFile() tiene buena información al respecto en "Consideraciones para trabajar con los identificadores de archivo sincrónicos", y "Consideraciones para trabajar con los identificadores de archivo asíncronas" en la sección "Sincronización de archivos y Posición".

banderas mango Prueba probablemente se debe hacer del mismo modo que las pruebas de los permisos del mango fue creado con. Intentalo. Si la API falla, probar el repliegue. Si eso falla, devolverá un error.

Creo que lo realmente diciendo es la forma en la documentación de ReadFile dice "Si hFile se abre con FILE_FLAG_OVERLAPPED, ... función puede informar incorrectamente que la operación de lectura se ha completado."

Mi interpretación del error es, (y la pregunta que hay que preguntarse es): si era posible comprobar el estado superpuesto de un identificador de archivo, ¿por qué READFILE no hacer el registro de entrada y luego validar la estructura OVERLAPPED consecuencia , a fallar de forma explícita si se llama de una manera no solapada con un mango superpuesto?

No sé una manera de determinar la bandera de un mango y los efectos secundarios del uso de ReOpen api, pero dado que su objetivo era

  

sería muy útil disponer de una sola manera de tratar a todos los mangos

Si usted desea un comportamiento síncrono (me refiero a usar API síncrono para no solapada asas y asincrónica API alimenta con estructura OVERLAPPED con la posterior espera en caso de solapado) siempre se puede utilizar la API asíncrona también si el mango se abrió en modo no solapado como se ha dicho por @Brett
Puedo confirmar que esto funciona (al menos para canalizaciones con nombre) es:

void connectSynchronous(HANDLE hPipeThatWeDontKnowItsFlag){
    ...
    BOOL bRet = ::ConnectNamedPipe(hPipeThatWeDontKnowItsFlag, pOverlapped);

    if(bRet == FALSE){
        DWORD dwLastErr = ::GetLastError();

        if(dwLastErr == ERROR_IO_PENDING){
            //The handle was opened for asynchronous IO so we have to wait for the operation
            ...waitFor on the overlapped hEvent;

        }else if(dwLastErr == ERROR_PIPE_CONNECTED){
            //The handle was opened for synchronous IO and the client was already connected before this call: that's OK!
            return;
        }else{
            throw Error(dwLastErr);
        }
    }/*else{
        //The handle was opened for synchronous IO and the client has connected: all OK
    }*/
}

Una alternativa al corte CreateIoCompletionPort es hacer un ReadFile cero bytes con un valor NULL lpOverlapped. Si se produce un error con ERROR_INVALID_PARAMETER asuma que se abrió con FILE_FLAG_OVERLAPPED.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top