Select模型(PIPE)
来源:互联网 发布:日本av作品番号数据库 编辑:程序博客网 时间:2024/06/07 04:54
这个模型也是最容易理解的
程序调用和我们基本的程序编写是一致的:
fd = connect()
write(fd)
read(fd)
close(fd)
程序的read必须在write之后执行,当write阻塞住了,read就不能执行下去
时候,也不阻塞程序,内核直接返回未准备就绪的信号,等待用户程序的下一次轮询。
#include <fcntl.h> int fcntl(int fd, int cmd, .. /* int arg */)
eg.
flags = flags | O_NONBLOCK;fcntl(fd, F_SETFL, flags);
IO复用模型是多了一个select函数,select函数有一个参数是文件描述符集合,意思就是对这些的文件描述符进行循环监听,当某个文件描述符就绪的时候,就对这个文件描述符进行处理。
这种IO模型是属于阻塞的IO。但是由于它可以对多个文件描述符进行阻塞监听,所以它的效率比阻塞IO模型高效
异步IO使用的不再是read和write的系统接口了,应用工程序调用aio_XXXX系列的内核接口。
当应用程序调用aio_read的时候,内核一方面去取数据报内容返回,另外一方面将程序控制权还给应用进程,应用进程继续处理其他事务。这样应用进程就是一种非阻塞的状态。
当内核的数据报就绪的时候,是由内核将数据报拷贝到应用进程中,返回给aio_read中定义好的函数处理程序。
select函数
#include<sys/select.h>
#include<sys/time.h>
int select (int maxfd , fd_set *readset ,fd_set *writeset, fd_set *exceptionset , const struct timeval * timeout);
返回:就绪描述字的正数目,0——超时,-1——出错
参数解释:
maxfd: 最大的文件描述符(其值应该为最大的文件描述符字 + 1)
readset: 内核读操作的描述符字集合
writeset:内核写操作的描述符字集合
exceptionset:内核异常操作的描述符字集合
timeout:等待描述符就绪需要多少时间。NULL代表永远等下去,一个固定值代表等待固定时间,0代表根本不等待,检查描述字之后立即返回。
注意:readset,writeset,exceptionset都是值-结果参数,意思就是他们传进入指针进去,函数根据指针可以修改对应的fd_set
fd_set集合操作
fd_set和名字一样,是一个描述符的集合。有下面几个操作:void FD_ZERO(fd_set *fdset); /* 将所有fd清零 */
void FD_SET(int fd, fd_set *fdset); /* 增加一个fd */
void FD_CLR(int fd, fd_set *fdset); /* 删除一个fd */
int FD_ISSET(int fd, fd_set *fdset); /* 判断一个fd是否有设置 */
下面以匿名管道程序,采用读非阻塞的select模型作为例子
jni:
#include<stdio.h>#include<stdlib.h>#include<unistd.h>#include<jni.h>#include<signal.h>#include<sys/select.h>#include<sys/time.h>#include <fcntl.h>#include <sys/types.h>#include<android/log.h>#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "native-activity", __VA_ARGS__))#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "native-activity", __VA_ARGS__))#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "native-activity", __VA_ARGS__))#ifndef NELEM# define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))#endifstatic char CLASS_NAME[] = "com/sailor/Select";static char CB_METHOD[] = "callBack";static int mWakeReadPipeFd = -1;static int mWakeWritePipeFd = -1;static struct timeval timeout={3,0};static fd_set fdset;static int maxfds = -1;static int nret = -1;void DestroyUnNamePipe(JNIEnv *env, jobject thiz){if(nret == 0){close(mWakeReadPipeFd);close(mWakeWritePipeFd);}}jint CreateUnNamePipe(JNIEnv *env, jobject thiz){int ret = -1;int result = -1;int fd[2];ret = pipe(fd);nret = ret;if(ret != 0){LOGE("create unname pipe error:%d" ,ret);}else{mWakeWritePipeFd = fd[1];mWakeReadPipeFd = fd[0];// 设置为非阻塞result = fcntl(mWakeReadPipeFd, F_SETFL, O_NONBLOCK);if(result != 0){LOGE("can not set to nonblock");}result = fcntl(mWakeWritePipeFd, F_SETFL, O_NONBLOCK);if(result != 0){LOGE("can not set to nonblock");}LOGE("set select mode");FD_ZERO(&fdset); //清空集合FD_SET(mWakeReadPipeFd, &fdset); //添加描述符 FD_SET(mWakeWritePipeFd, &fdset); //添加描述符 maxfds = (fd[1] > fd[0])?fd[1]+1:fd[0]+1; }return ret;}void ReadUNPMessage(JNIEnv *env, jobject thiz){int select_ret;int ret = -1;/*select_ret = select(maxfds,&fd_set,NULL,NULL,&timeout);*/while(1){LOGE("select start");select_ret = select(maxfds, &fdset, NULL, NULL, NULL);LOGE("read ret:%d" , select_ret);if(select_ret > 0){if(FD_ISSET(mWakeReadPipeFd, &fdset) && nret == 0){//call java methodchar buffer[80+1];memset(buffer, 0, sizeof(buffer));ret = read(mWakeReadPipeFd, buffer, sizeof(buffer));LOGE("read ret:%d" , ret);if(ret == -1)return ;else{jbyteArray array = (*env)->NewByteArray(env, sizeof(buffer));(*env)->SetByteArrayRegion(env, array, 0, sizeof(buffer), (char *)buffer);jclass jhandlerClass = (*env)->GetObjectClass(env, thiz); jmethodID doActionMethodId = (*env)->GetMethodID(env, jhandlerClass, CB_METHOD, "([B)V"); (*env)->CallVoidMethod(env, thiz, doActionMethodId, array); (*env)->ReleaseByteArrayElements(env, array, buffer, 0);}}}}return ;}jint SendUNPMessage(JNIEnv *env, jobject thiz, jstring message){int ret = -1;if(nret == 0){const char *pMsg = (*env)->GetStringUTFChars(env, message, 0);ret = write(mWakeWritePipeFd, pMsg, strlen(pMsg));LOGE("send ret: %d", ret);(*env)->ReleaseStringUTFChars(env, message, pMsg);}return ret;}static JNINativeMethod mehods[] = {{ "createUnNamePipe", "()I", (void *) CreateUnNamePipe },{ "sendUNPMessage", "(Ljava/lang/String;)I", (void *) SendUNPMessage },{ "readUNPMessage", "()V", (void *) ReadUNPMessage },{ "destroyUnNamePipe", "()V", (void *) DestroyUnNamePipe }};static int registerNativeMethods(JNIEnv *env, const char* className, const JNINativeMethod* methods, int numMethods){ int rc; jclass clazz; clazz = (*env)->FindClass(env, className); if (clazz == NULL) { LOGE("Native registration unable to find class '%s'\n", className); return -1; } if (rc = ((*env)->RegisterNatives(env, clazz, methods, numMethods)) < 0) { LOGE("RegisterNatives failed for '%s' %d\n", className, rc); return -1; } return 0;}static int register_jni(JNIEnv *env){return registerNativeMethods(env, CLASS_NAME, mehods, NELEM(mehods));}JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved){ JNIEnv* env = NULL; jint result = -1; //获取JNI版本 if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_4) != JNI_OK) { LOGE("GetEnv failed!"); return result; } if (register_jni(env) < 0) {LOGE("register method failed!"); return result; } return JNI_VERSION_1_4;}
java类:
package com.sailor;import android.util.Log;public class Select {static {// 加载动态库System.loadLibrary("JNISelect");}public native int createUnNamePipe();public native int sendUNPMessage(String msg);public native void readUNPMessage();public native void destroyUnNamePipe();public void callBack(byte[] buffer){Log.d("jacklam", "read msg:" + new String(buffer));}}
调用:
public void startSelect3(View view){if(select != null)select.destroyUnNamePipe();}public void startSelect2(View view){if(select != null){select.sendUNPMessage("test select mode");}/*mem.close(fd);*/}public void startSelect1(View view){select = new Select();select.createUnNamePipe();Thread thread = new Thread(new Runnable() {@Overridepublic void run() {select.readUNPMessage();}});thread.start();/*mem.close(fd);*/}
显示结果:
- Select模型(PIPE)
- select pipe
- windows select pipe
- 选择(select)模型
- select:windows pipe的模拟
- pipe unblock select in linux
- 一、选择模型(select)
- socket select模型(一)
- socket select模型(三)
- select 模型
- select模型
- Select模型
- Select模型
- Select模型
- SELECT模型
- select模型
- Select模型
- SELECT模型
- 小白学c++之sublime2激活
- HTML5 Canvas 旋转
- 设计模式学习笔记--迭代(Iterator)模式
- tomcat启动失败
- Android ViewGroup拦截触摸事件详解
- Select模型(PIPE)
- how to remove nil and blank string in an array in Ruby
- Android 分享功能,过滤掉不需要的组件,解决出现“Android系统“问题
- xcode工程的文件夹类型 folder References group
- 超越Administrator的权限
- 关于Handler、 Looper 、MessageQueue的认识
- 必须掌握的八个DOS命令
- Valid Parentheses
- PDU编码规则