由于usbip相关代码使用了giochannel,该部分功能包含于glib中,所以找到此文以做翻译。
Using GIOChannel
GIOChannel provides a portable method for using file descriptors, sockets and pipes and integrating them into the GLib main loop.
GIOChannel提供一种很方便的可以用于文件描述符,套接字和管道并且将他们集成到glib的主循环的方法。
The g_io_channel_unix_new() API takes a file descriptor as an input parameter and is used to create a new GIOChannel.
g_io_channel_unix_new() API 将一个文件描述符作为输入参数并且用其产生一个新的GIOChannel。
Alternatively, the g_io_channel_new_file() API can be used to create a channel for a file. Once the channel is created, it can be used in a generic manner.
另外,g_io_channel_new_file() API用于为一个文件创造一个io通道(相比较上面是为文件描述符创造io通道)。一旦通道建立,它就可以被用于常规的方式。
To read a channel, APIs such as the following can be used:
下面的API可以被用于读取一个通道:
-
g_io_channel_read_chars()
-
g_io_channel_read_line()
-
g_io_channel_read_to_end()
To write to a channel an API like g_io_channel_write_chars() is used.
像是g_io_channel_write_chars这样的API可以被用于向一个通道中写入数据。
To set the position in the current GIOChannel, g_io_channel_seek_position() can be used.
若是想在当前的GIOChannel中设置位置,那么g_io_channel_seek_position()会被用到。
Finally the channel can be closed using g_io_channel_shutdown().
最后通道可以使用g_io_channel_shutdown()关闭。
The following is an example code where a file descriptor to a plain file is used to create a GIOChannel, and then the contents of the file are read in chunks of 100 bytes and printed using g_print. Finally the channel is closed.
如下是一个示例代码,代码描述了使用一个普通文件的文件描述符创建一个GIOChannel,然后改文件的内容被按照100byte每块的方式读取并且使用g_print打印出来,最后该通道被关闭。
#include <glib.h> #include <stdio.h> int main(int argc, char *argv[]) { GIOChannel *channel; gchar buf[100]; gsize bytes_read; FILE *fp; if(argc != 2) { g_print("usage:cat <file_name>\n"); g_print("Press any key to exit\n"); getchar(); return 1; } fp = fopen(argv[1],"r"); if(!fp) { g_print("Unable to open the file %s\n",argv[1]); return 1; } channel = g_io_channel_unix_new(fileno(fp)); do { g_io_channel_read_chars(channel,buf,100,&bytes_read,NULL); g_print("%s",buf); } while(bytes_read > 0); g_io_channel_shutdown(channel,TRUE,NULL); fclose(fp); return 0; }
In the example below, a sample code to copy a file is written. In the code, channels are opened using g_io_channel_new_file(). The contents of the file are read using g_io_channel_read_chars(), and the contents are written to a new file using g_io_channel_write_chars().
在如下的示例中,代码被用于拷贝一个文件。在如下代码中,通道使用g_io_channel_new_file API打开文件。文件的内容使用g_io_channel_read_chars API读取数据,文件内容使用g_io_channel_write_chars API写入到一个新文件中去
#include <glib.h> #include <stdio.h> int main(int argc, char *argv[]) { GIOChannel *in_channel,*out_channel; gchar buf[100]; gsize bytes_read,bytes_written; GError *error = NULL; if(argc != 3) { g_print("usage:<cp SOURCE> <DESTINATION>\n"); g_print("Press any key to exit\n"); getchar(); return 1; } in_channel = g_io_channel_new_file(argv[1],"r",&error); if(!in_channel) { g_print("Unable to open the file %s to read\n",argv[1]); g_print("Press any key to exit\n"); getchar(); return 1; } out_channel = g_io_channel_new_file(argv[2],"w",&error); if(!out_channel) { g_print("Unable to open the file %s to write\n",argv[2]); g_print("Press any key to exit\n"); getchar(); return 1; } do { g_io_channel_read_chars(in_channel,buf,100,&bytes_read,&error); if(error) { g_print("Error while reading file %s\n",argv[1]); g_print("Press any key to exit\n"); getchar(); return 1; } g_io_channel_write_chars(out_channel,buf,bytes_read,&bytes_written,&error); if(error) { g_print("Error while writing file %s\n",argv[2]); g_print("Press any key to exit\n"); getchar(); return 1; } } while(bytes_read > 0); g_io_channel_shutdown(in_channel,TRUE,&error); if(error) { g_print("Error has occured\n"); g_print("Press any key to exit\n"); getchar(); return 1; } g_io_channel_shutdown(out_channel,TRUE,&error); if(error) { g_print("Error has occured\n"); g_print("Press any key to exit\n"); getchar(); return 1; } g_print("File copied successfully...\n"); getchar(); return 0; }
Using GIOChannel in GLib main loops
GIOChannel provides a way to integrate file descriptors to main loops. The following code demonstrates the usage. In the code, a pipe is created. A thread is created which writes to the write end of the pipe. The main loop checks if the other end of the pipe is ready to read. If it is, then the callback function is called. The callback calls g_main_loop_quit(), and the main loop is terminated and g_main_loop_run()returns.
GIOChannel 提供一个方法去集成文件描述符到主循环当中(main loops)。如下代码演示使用方法。在如下代码中,管道被创建,一个线程被创建并且向管道末端写入数据。主循环检查其他管道末端是否准备好去读取。如果条件满足,回调函数就会被调用。回调函数调用g_main_loop_quit,并且主循环终止于g_main_loop_run函数的返回。
#include <glib.h> #include <stdio.h> int fd[2]; void *thread_function(void *data) { // call sleep so that the main loop source is not ready immediately sleep(10); write(fd[1],"GIOChannel main loop example",29); return NULL; } gboolean my_callback(GIOChannel *source,GIOCondition condition,gpointer data) { char buf[100]; read(fd[0],buf,sizeof(buf)); g_print("%s",buf); getchar(); g_main_loop_quit((GMainLoop *)data); return FALSE; } int main() { GMainLoop *loop; GIOChannel *channel; pipe(fd); channel = g_io_channel_unix_new(fd[0]); g_thread_init(NULL); g_thread_create(thread_function,NULL,TRUE,NULL); loop = g_main_loop_new(NULL,FALSE); g_io_add_watch(channel,G_IO_IN | G_IO_HUP | G_IO_ERR,(GIOFunc)my_callback,loop); g_main_loop_run(loop); g_io_channel_shutdown(channel,TRUE,NULL); return 0; }