glib源码下载:http://ftp.gnome.org/pub/gnome/sources/glib/
glib帮助文档:https://developer.gnome.org/glib/

IO通道 - 可移植的支持使用文件,管道和套接字

Includes
#include <glib.h>

描述

GIOChannel数据类型旨在提供一种可移植的方法,用于使用文件描述符,管道和套接字,并将它们集成到main event loop。 目前,在UNIX平台上提供完全支持,对Windows的支持仅部分完成。
要在UNIX系统上创建新的GIOChannel,请使用g_io_channel_unix_new()。 这适用于普通文件描述符,管道和套接字。 或者,可以使用g_io_channel_new_file()以与系统无关的方式为文件创建通道。
创建GIOChannel后,可以使用函数g_io_channel_read_chars(),g_io_channel_write_chars(),g_io_channel_seek_position()和g_io_channel_shutdown()以通用方式使用它。
要将GIOChannel添加到main event loop,请使用g_io_add_watch()或g_io_add_watch_full()。 在这里,您可以在GIOChannel上指定您感兴趣的事件,并提供在发生这些事件时要调用的函数。
创建GIOChannel实例,初始引用计数为1. g_io_channel_ref()和g_io_channel_unref()可分别用于递增或递减引用计数。 当引用计数降至0时,释放GIOChannel。 (虽然它不会自动关闭,除非它是使用g_io_channel_new_file()创建的。)使用g_io_add_watch()或g_io_add_watch_full()增加通道的引用计数。
新函数g_io_channel_read_chars(),g_io_channel_read_line(),g_io_channel_read_line_tring(),g_io_channel_read_to_end(),g_io_channel_write_chars(),g_io_channel_seek_position()和g_io_channel_flush()不应与不推荐使用的函数g_io_channel_read(),g_io_channel_write()和g_io_channel_seek混合使用( )在同一channel上。

函数

g_io_channel_unix_new ()
给定文件描述符创建新的GIOChannel。 在UNIX系统上,这适用于普通文件,管道和套接字。
返回的GIOChannel的引用计数为1。
GIOChannel的默认编码是UTF-8。 如果您的应用程序正在使用via管道从命令读取输出,则可能需要使用g_io_channel_set_encoding()函数将编码设置为当前语言环境的编码(请参阅g_get_charset())。 默认情况下,当删除对GIOChannel数据结构的最终引用时,将不会关闭传递的fd。
如果要在没有解释的情况下读取原始二进制数据,则使用NULL为编码参数调用g_io_channel_set_encoding()函数。
此功能在Windows上的GLib中也可用,但您应该避免在Windows上使用它。 文件描述符和套接字的域重叠。 如果传递给此函数的参数恰好是有效的文件描述符和套接字,则GLib无法知道您的意思。 如果发生这种情况,则会发出警告,并且GLib假定它是您所指的文件描述符。
返回值
一个新的GIOChannel。
g_io_channel_unix_get_fd ()
返回GIOChannel的文件描述符。
在Windows上,此函数返回GIOChannel的文件描述符或套接字。

g_io_channel_init ()
初始化GIOChannel结构。
在创建GIOChannel时,上述每个函数都会调用它,因此应用程序员通常不需要这样做(除非您要创建新类型的GIOChannel)。

g_io_channel_new_file ()
使用mode模式将文件文件名作为GIOChannel打开。 当删除对它的最后一个引用时,该channel将被关闭,因此不需要调用g_io_channel_close()(尽管这样做不会导致问题,只要在关闭后没有尝试访问该通道)。
参数
mode
 “r”,“w”,“a”,“r +”,“w +”,“a +”之一。 这些与fopen()中的含义相同
返回值
成功时的GIOChannel,失败时为NULL。
g_io_channel_read_chars ()
使用新API替换g_io_channel_read()。
参数
count
缓冲区的大小。 请注意,如果剩余数据不是完整字符,即使缓冲区中有数据,缓冲区也可能无法完全填充。
[in]
bytes_read
读取的字节数。 如果count <6并且channel的编码为非NULL,则即使成功也可能为零。 这表示下一个UTF-8字符对于缓冲区来说太宽。
[out][optional]

返回值
操作的状态。
g_io_channel_read_unichar ()
从通道读取Unicode字符。 无法在具有NULL编码的通道上调用此函数。

g_io_channel_read_line ()
从GIOChannel读取一行(包括终止字符)到新分配的字符串。 如果返回值为G_IO_STATUS_NORMAL,则str_return将包含已分配的内存。
参数
str_return
从GIOChannel读取的行,包括行终止符。 不再需要时,应使用g_free()释放此数据。 这是一个以空字符结尾的字符串。 如果返回零长度,则将为NULL。
[out]
length
存储读取数据长度的位置,或NULL。
[out][optional]
terminator_pos

存储行终止符位置的位置,或NULL。
[out][optional]
error

返回GConvertError或GIOChannelError类型错误的位置
返回值
操作的状态。
g_io_channel_read_line_string ()
使用GString作为缓冲区从GIOChannel读取一行。
参数
g_io_channel_read_to_end ()
从文件中读取所有剩余数据。
返回值
G_IO_STATUS_NORMAL成功。 此函数永远不会返回G_IO_STATUS_EOF。
g_io_channel_write_unichar ()
将Unicode字符写入通道。 无法在具有NULL编码的通道上调用此函数。

g_io_channel_flush ()
刷新GIOChannel的写缓冲区。
返回值
操作的状态:G_IO_STATUS_NORMAL,G_IO_STATUS_AGAIN或G_IO_STATUS_ERROR之一。
g_io_channel_shutdown ()
关闭IO通道。 如果flush为TRUE,则将刷新任何要写入的待处理数据。 在使用g_io_channel_unref()删除最后一个引用之前,不会释放该通道。
g_io_create_watch ()
创建在满足给定通道条件时调度的GSource。 例如,如果condition是G_IO_IN,则当有可用于读取的数据时,将调度source。
对于您希望以默认优先级将source添加到默认主循环上下文的情况,g_io_add_watch()是同一功能的简单接口。

g_io_add_watch ()
使用默认优先级将GIOChannel添加到默认主循环上下文中。
g_io_add_watch_full ()
将GIOChannel添加到具有给定优先级的默认主循环上下文中。
这在内部使用g_io_create_watch()创建一个主循环source,并使用g_source_attach()将其附加到主循环上下文。 如果需要更好的控制,可以手动执行这些步骤。
[rename-to g_io_add_watch]

gboolean
(*GIOFunc) (GIOChannel *source,
            GIOCondition condition,
            gpointer data);
指定传递给g_io_add_watch()或g_io_add_watch_full()的函数类型,该函数在满足GIOChannel上的请求条件时调用。

g_io_channel_get_line_term ()
这将返回GIOChannel用于确定文件在哪里发生换行的字符串。 值NULL表示自动检测。
g_io_channel_set_line_term ()
这将设置GIOChannel用于确定文件中断行发生位置的字符串。

g_io_channel_get_buffered ()
返回缓冲通道。
g_io_channel_set_buffered ()
只有在通道编码为NULL时才能设置缓冲状态。 对于任何其他编码,必须缓冲通道。
如果刷新了通道的内部缓冲区,则只能将缓冲通道设置为无缓冲。 返回G_IO_STATUS_EOF的新创建的频道或频道不需要这样的flush。 对于只写通道,调用g_io_channel_flush()就足够了。 对于所有其他通道,可以通过调用g_io_channel_seek_position()来刷新缓冲区。 这包括寻找类型G_SEEK_CUR和零偏移的可能性。 请注意,这意味着一旦从其中读取数据,就无法将基于套接字的通道设置为无缓冲。
在无缓冲通道上,如果维护旧代码是必要的,则可以安全地混合来自新旧API的读写调用。
缓冲通道的默认状态。

示例代码:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <glib.h>
#include <glib/gprintf.h>void channel_unix_new_test(void)
{g_printf ("%s() in\n", __func__);int fd = open("test.txt", O_RDONLY);GIOChannel *giofile = g_io_channel_unix_new (fd);gchar *str_return;gsize length, terminator_pos;GError *error = NULL;GIOStatus giostatus = g_io_channel_read_line (giofile,&str_return,&length,&terminator_pos,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_line:%s, length:%ld, terminator_pos:%ld\n", str_return, length, terminator_pos);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_line error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_line error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_line error G_IO_STATUS_AGAIN:%s\n", error->message);GString *buffer = g_string_new (NULL);giostatus = g_io_channel_read_line_string (giofile,buffer,&terminator_pos,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_line_string:%s\n", buffer->str);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_line_string error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_line_string error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_line_string error G_IO_STATUS_AGAIN:%s\n", error->message);g_string_free (buffer, TRUE);giostatus = g_io_channel_read_to_end (giofile,&str_return,&length,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_to_end:%s, length:%ld\n", str_return, length);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_to_end error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_to_end error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_to_end error G_IO_STATUS_AGAIN:%s\n", error->message);gint gfd = g_io_channel_unix_get_fd (giofile);g_io_channel_shutdown (giofile, TRUE, &error);close(gfd);g_printf ("%s() out\n", __func__);
}void channel_read_chars_test(void)
{g_printf ("%s() in\n", __func__);GError *error = NULL;GIOChannel *giofile = g_io_channel_new_file ("test.txt","r",&error);gchar *buf = g_new0(gchar, 1024);gsize bytes_read;GIOStatus giostatus = g_io_channel_read_chars (giofile,buf,1024,&bytes_read,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_chars:%s, length:%ld\n", buf, bytes_read);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_chars error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_chars error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_chars error G_IO_STATUS_AGAIN:%s\n", error->message);g_io_channel_shutdown (giofile, TRUE, &error);g_free (buf);g_printf ("%s() out\n", __func__);
}void channel_read_unichar_test(void)
{g_printf ("%s() in\n", __func__);GError *error = NULL;GIOChannel *giofile = g_io_channel_new_file ("ansi.txt","r",&error);GError *err = NULL;GIOStatus giostatus = g_io_channel_set_encoding (giofile,"ANSI",&err);gunichar thechar;giostatus = g_io_channel_read_unichar (giofile,&thechar,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_unichar:%d\n", thechar);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_unichar error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_unichar error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_unichar error G_IO_STATUS_AGAIN:%s\n", error->message);g_io_channel_shutdown (giofile, TRUE, &error);g_printf ("%s() out\n", __func__);
}void channel_write_chars_test(void)
{g_printf ("%s() in\n", __func__);GError *error = NULL;GIOChannel *giofile = g_io_channel_new_file ("write.txt","a+",&error);gsize bytes_written;GIOStatus giostatus = g_io_channel_write_chars (giofile,"g_io_channel_write_chars",-1,&bytes_written,&error);if (giostatus == G_IO_STATUS_ERROR)g_printf ("write_chars error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("write_chars error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("write_chars error G_IO_STATUS_AGAIN:%s\n", error->message);giostatus = g_io_channel_flush (giofile,&error);if (giostatus == G_IO_STATUS_ERROR)g_printf ("flush error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("flush error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("flush error G_IO_STATUS_AGAIN:%s\n", error->message);g_io_channel_shutdown (giofile, TRUE, &error);g_printf ("%s() out\n", __func__);
}gboolean GIOFifoFunc (GIOChannel *source, GIOCondition condition, gpointer data)
{g_printf ("GIOFifoFunc data:%s\n", (char *)data);g_printf ("condition:%d\n", condition);if(condition & G_IO_HUP) {g_error("error:Pipe Disconnected!\n");}GError *error = NULL;gsize bytes_read;gsize length, terminator_pos;gchar *str_return;GIOStatus giostatus = g_io_channel_read_line (source,&str_return,&length,&terminator_pos,&error);if (giostatus == G_IO_STATUS_NORMAL)g_printf ("read_line:%s, length:%ld, terminator_pos:%ld\n", str_return, length, terminator_pos);else if (giostatus == G_IO_STATUS_ERROR)g_printf ("read_chars error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("read_chars error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("read_chars error G_IO_STATUS_AGAIN:%s\n", error->message);g_free (str_return);return TRUE;
}void FifoDestroyNotify (gpointer data)
{g_printf ("FifoDestroyNotify data:%s\n", (char *)data);
}gboolean TimeoutSourceFunc (gpointer user_data)
{g_printf ("%s() in\n", __func__);GMainLoop *loop = (GMainLoop *)user_data;g_main_loop_quit (loop);return FALSE;
}void setup_child(gint input[]) {g_printf ("%s() in\n", __func__);GIOChannel *channel_read;char *user_data = "test user data!";// 关闭不必要的 Pipe 输入close(input[1]);GMainLoop *loop = g_main_loop_new (NULL, FALSE);channel_read = g_io_channel_unix_new(input[0]);if(channel_read == NULL) {g_error("error:Unable to establish GIOChannels!\n");}guint source_id = g_io_add_watch_full(channel_read, G_PRIORITY_DEFAULT, G_IO_IN|G_IO_HUP, GIOFifoFunc, (gpointer) user_data, FifoDestroyNotify);if(source_id == 0) {g_error("error:Unable to add watch!\n");}g_timeout_add (1000, TimeoutSourceFunc, (gpointer)loop);g_main_loop_run (loop);g_source_remove (source_id);g_printf ("g_source_remove\n");sleep(1);
}void setup_parent(gint output[]) {g_printf ("%s() in\n", __func__);sleep(1);GIOChannel *channel_write;GError *error = NULL;gsize bytes_written;// 关闭不用的 Pipe 输出close(output[0]);// 建立 GIOChannelchannel_write = g_io_channel_unix_new(output[1]);if(channel_write == NULL) {g_error("错误:无法建立 GIOChannels!\n");}GIOStatus giostatus = g_io_channel_write_chars (channel_write,"setup parent\n",-1,&bytes_written,&error);giostatus = g_io_channel_flush (channel_write, &error);if (giostatus == G_IO_STATUS_ERROR)g_printf ("flush error G_IO_STATUS_ERROR:%s\n", error->message);else if (giostatus == G_IO_STATUS_EOF)g_printf ("flush error G_IO_STATUS_EOF:%s\n", error->message);else if (giostatus == G_IO_STATUS_AGAIN)g_printf ("flush error G_IO_STATUS_AGAIN:%s\n", error->message);sleep(5);
}void io_add_watch(void)
{g_printf ("%s() in\n", __func__);gint parent_to_child[2];if(pipe(parent_to_child) == -1) { // 开启Pipeg_error("Error:%s\n", g_strerror(errno));return;}// fork 子程序switch(fork()) {case -1:g_error("error:%s\n", g_strerror(errno));break;case 0: // 这是子程序setup_child(parent_to_child);break;default: // 这是父程序setup_parent(parent_to_child);}g_printf ("%s() out\n", __func__);
}int main(int argc, char **argv)
{g_printf ("main() in\n");channel_unix_new_test();channel_read_chars_test();channel_read_unichar_test();channel_write_chars_test();io_add_watch();g_printf ("main() out\n");return 0;
}

输出结果:

~/glibtest$ ./gio
main() in
io_add_watch() in
setup_parent() in
setup_child() in
GIOFifoFunc data:test user data!
condition:1
read_line:setup parent
, length:13, terminator_pos:12
TimeoutSourceFunc() in
FifoDestroyNotify data:test user data!
g_source_remove
io_add_watch() out
main() outio_add_watch() out
main() out

文本文件:

ansi.txt

test.txt

write.txt

Glib学习(23) IO通道 IO Channels相关推荐

  1. 深入学习java非阻塞IO

    深入学习java非阻塞IO 三大组件: 1. Channel:数据通道双向通道 (1)常见的channel: FileChannel:文件传输通道 DatagramChannel:UDP传输通道 So ...

  2. Python学习笔记:异步IO(3)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  3. Python学习笔记:异步IO(2)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  4. Python学习笔记:异步IO(1)

    前言 最近在学习深度学习,已经跑出了几个模型,但Pyhton的基础不够扎实,因此,开始补习Python了,大家都推荐廖雪峰的课程,因此,开始了学习,但光学有没有用,还要和大家讨论一下,因此,写下这些帖 ...

  5. spark集群环境下Lost task 0.0 in stage 10.0 (TID 17, 10.28.23.202): java.io.FileNotFoundException

    spark从当前目录加载文件报错,Lost task 0.0 in stage 10.0 (TID 17, 10.28.23.202): java.io.FileNotFoundException,明 ...

  6. 计算机的I/O设备及I/O设备控制方式(DMA、IO通道)

    目录 I/O设备 设备控制器 对IO设备的控制方式 DMA(直接内存访问) 通道 I/O设备 除了CPU和主存外,计算机系统的每一部分都可作为一个外围设备来看待.外围设备的功能是在计算机和其他机器之间 ...

  7. 一个编程小白的Java SE学习日志 X—— 输入输出(IO)流【极客BOY-米奇】

    文章目录 前言(转载请说明作者!)4.30~5.7编写 File类 File类的构造方法 File类常用方法 File类的一些常用方法实例 IO流 IO流的分类 按数据流的方向分类 按是否直接操作源或 ...

  8. 5分钟学习23种设计模式

    文章目录 5分钟学习23种设计模式 阿里巴巴开发手册 七大设计原则 设计模式类型 1.单例模式 2.简单工厂模式 3.工厂模式 4.抽象工厂模式 5.装饰器模式 6.适配器模式 7.观察者模式 8.外 ...

  9. 深入浅出asterisk(一):asterisk通道(Channels)

    由于工作上的VOIP项目需要,最近亲密接触了一下asterisk工程代码.关于asterisk在VOIP上的伟大地位和作用,俺就不絮叨了,请看前作:Astersik+Radius简易攻略     国内 ...

最新文章

  1. 自创设计模式-----答题卡模式
  2. .Net(c#) 通过 Fortran 动态链接库,实现混合编程
  3. HDU - 6599 I Love Palindrome String (回文树+Manacher、回文树+hash)
  4. js实现替换指定字符后面的内容(包括指定字符)
  5. POJ2115-C Looooops【扩欧,同余】
  6. 检测到目标url存在内部ip地址泄露_Cendertron,动态爬虫与敏感信息泄露检测
  7. The Two Routes CodeForces - 601A(水最短路)
  8. ubuntu14.04 x86编译upx 3.92 及so加固
  9. mysql1714_linux环境安装mysql
  10. h5 video全屏播放
  11. 吴恩达机器学习作业Python实现(二):logistic回归
  12. 3.1.4 抽象类与归一化
  13. RAC性能分析 - gc buffer busy acquire 等待事件
  14. MySQL连接问题 --- (1251:Client does not support ...)
  15. C++编译器优化:Copy Elision(省略不必要的拷贝)
  16. [面向对象程序设计] 汽车租赁系统(Java实现)
  17. [转载]微信公众号开发 [01] 入门基本流程
  18. HNU君陌:写一点文艺的东西
  19. 嘀,你有一份1024礼物待查收!
  20. 祝朋友们端午节快乐!

热门文章

  1. 数字化孪生技术在打造智慧工地上的应用
  2. 简单易懂云计算(转自天涯感谢原楼主iamsatisfied)
  3. 阿里大股东Altaba准备清算解散 所持阿里股份也计划全部出售
  4. 五子棋你都下不赢别人?那还不快用我这个去练练手。制作非常简单。
  5. ArangoDB图形数据库(基础简介)
  6. 深圳:一个月拿多少钱才不算是穷人?
  7. 剧本杀app开发设计IU
  8. 【MYSQL的QA】
  9. 想知道图片编辑修改文字怎么操作吗
  10. 2021年高考佛山成绩查询,2021年佛山高考各高中成绩及本科升学率数据排名及分析...