frame,cookie,this对象

本文深入讲解了HTML中的frame框架对象的使用方法及注意事项,并详细解释了Cookie的基本知识、设置方法及如何通过JavaScript获取和删除Cookie。
frame 框架对象
--使用方法
----用最容易理解的话说,每一个 HTML 文件占用一个 window 对象,包括定义框架的网页(“框架网页”)。在 IE 里用“<iframe>”标记在文档中插入的框架也是 window 对象,但是用“包含网页”的方法(在 HTML 中显示为“<!--webbot bot="include" ...-->”)读取的 HTML 就不占用独自的 window 对象。每一个框架都是包含它的页的 window 对象的一个子对象(不知道应该叫“属性”不该),要引用它,可以用以下几种方法之一:window.frames[x]
window.frames['frameName']
window.frameName
----使用框架还要密切留意你的 JavaScript 中定义的全局变量和自定义函数。它们都有它们的所属所在的 window 对象。要引用其它框架中的全局变量或自定义函数,都要用“窗口对象.框架对象[.框架对象…].全局变量或自定义函数”这种很烦的方法。

cookie
--基本知识
----<cookie名>=<值>
----每个 Cookie 都有失效日期,一旦电脑的时钟过了失效日期,这个 Cookie 就会被删掉。我们不能直接删掉一个 Cookie,但是可以用设定失效日期早于现在时刻的方法来间接删掉它。
--document.cookie
----内容格式:name=kevin; email=kevin@kevin.com; lastvisited=index.html
两个 Cookies 之间是用分号和空格隔开的,于是我们可以用 cookieString.split('; ') 方法得到每个 Cookie 分开的一个数组(先用 var cookieString = document.cookie)。
----设定一个“name=rose”的 Cookie,在 3 个月后过期。
var expires = new Date();
expires.setTime(expires.getTime() + 3 * 30 * 24 * 60 * 60 * 1000);
/* 三个月 x 一个月当作 30 天 x 一天 24 小时
x 一小时 60 分 x 一分 60 秒 x 一秒 1000 毫秒 */
document.cookie = 'name=rose;expires=' + expires.toGMTString();
----删除刚才设定的 name=rose Cookie。
var expires = new Date();
expires.setTime(expires.getTime() - 1);
document.cookie = 'name=rose;expires=' + expires.toGMTString();
----编写一个函数,作用是查找指定 Cookie 的值。
function getCookie(cookieName) {
var cookieString = document.cookie;
var start = cookieString.indexOf(cookieName + '=');
// 加上等号的原因是避免在某些 Cookie 的值里有
// 与 cookieName 一样的字符串。
if (start == -1) // 找不到
return null;
start += cookieName.length + 1;
var end = cookieString.indexOf(';', start);
if (end == -1) return unescape(cookieString.substring(start));
return unescape(cookieString.substring(start, end));
}

this对象
--返回“当前”对象
--如果在 JavaScript 的“主程序”中(不在任何 function 中,不在任何事件处理程序中)使用 this,它就代表 window 对象;如果在 with 语句块中使用 this,它就代表 with 所指定的对象;如果在事件处理程序中使用 this,它就代表发生事件的对象。
<script>
...
function check(formObj) {
...
}
...
</script>
<body ...>
...
<form ...>
...
<input type="text" ... onchange="check(this.form)">
...
</form>
...


本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/cjfspider/archive/2005/03/18/322773.aspx
status_t IPCThreadState::executeCommand(int32_t cmd) { BBinder* obj; RefBase::weakref_type* refs; status_t result = NO_ERROR; switch ((uint32_t)cmd) { case BR_ERROR: result = mIn.readInt32(); break; case BR_OK: break; case BR_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); ALOG_ASSERT(refs->refBase() == obj, "BR_ACQUIRE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); obj->incStrong(mProcess.get()); IF_LOG_REMOTEREFS() { LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj); obj->printRefs(); } mOut.writeInt32(BC_ACQUIRE_DONE); mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; case BR_RELEASE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); ALOG_ASSERT(refs->refBase() == obj, "BR_RELEASE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); IF_LOG_REMOTEREFS() { LOG_REMOTEREFS("BR_RELEASE from driver on %p", obj); obj->printRefs(); } mPendingStrongDerefs.push(obj); break; case BR_INCREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); refs->incWeak(mProcess.get()); mOut.writeInt32(BC_INCREFS_DONE); mOut.writePointer((uintptr_t)refs); mOut.writePointer((uintptr_t)obj); break; case BR_DECREFS: refs = (RefBase::weakref_type*)mIn.readPointer(); // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) obj = (BBinder*)mIn.readPointer(); // consume // NOTE: This assertion is not valid, because the object may no // longer exist (thus the (BBinder*)cast above resulting in a different // memory address). //ALOG_ASSERT(refs->refBase() == obj, // "BR_DECREFS: object %p does not match cookie %p (expected %p)", // refs, obj, refs->refBase()); mPendingWeakDerefs.push(refs); break; case BR_ATTEMPT_ACQUIRE: refs = (RefBase::weakref_type*)mIn.readPointer(); obj = (BBinder*)mIn.readPointer(); { const bool success = refs->attemptIncStrong(mProcess.get()); ALOG_ASSERT(success && refs->refBase() == obj, "BR_ATTEMPT_ACQUIRE: object %p does not match cookie %p (expected %p)", refs, obj, refs->refBase()); mOut.writeInt32(BC_ACQUIRE_RESULT); mOut.writeInt32((int32_t)success); } break; case BR_TRANSACTION_SEC_CTX: case BR_TRANSACTION: { binder_transaction_data_secctx tr_secctx; binder_transaction_data& tr = tr_secctx.transaction_data; if (cmd == (int) BR_TRANSACTION_SEC_CTX) { result = mIn.read(&tr_secctx, sizeof(tr_secctx)); } else { result = mIn.read(&tr, sizeof(tr)); tr_secctx.secctx = 0; } ALOG_ASSERT(result == NO_ERROR, "Not enough command data for brTRANSACTION"); if (result != NO_ERROR) break; Parcel buffer; buffer.ipcSetDataReference( reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer), tr.data_size, reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets), tr.offsets_size/sizeof(binder_size_t), freeBuffer); const void* origServingStackPointer = mServingStackPointer; mServingStackPointer = __builtin_frame_address(0); const pid_t origPid = mCallingPid; const char* origSid = mCallingSid; const uid_t origUid = mCallingUid; const bool origHasExplicitIdentity = mHasExplicitIdentity; const int32_t origStrictModePolicy = mStrictModePolicy; const int32_t origTransactionBinderFlags = mLastTransactionBinderFlags; const int32_t origWorkSource = mWorkSource; const bool origPropagateWorkSet = mPropagateWorkSource; // Calling work source will be set by Parcel#enforceInterface. Parcel#enforceInterface // is only guaranteed to be called for AIDL-generated stubs so we reset the work source // here to never propagate it. clearCallingWorkSource(); clearPropagateWorkSource(); mCallingPid = tr.sender_pid; mCallingSid = reinterpret_cast<const char*>(tr_secctx.secctx); mCallingUid = tr.sender_euid; mHasExplicitIdentity = false; mLastTransactionBinderFlags = tr.flags; // ALOGI(">>>> TRANSACT from pid %d sid %s uid %d\n", mCallingPid, // (mCallingSid ? mCallingSid : "<N/A>"), mCallingUid); Parcel reply; status_t error; IF_LOG_TRANSACTIONS() { std::ostringstream logStream; logStream << "BR_TRANSACTION thr " << (void*)pthread_self() << " / obj " << tr.target.ptr << " / code " << TypeCode(tr.code) << ": \t" << buffer << "\n" << "Data addr = " << reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer) << ", offsets addr=" << reinterpret_cast<const size_t*>(tr.data.ptr.offsets) << "\n"; std::string message = logStream.str(); ALOGI("%s", message.c_str()); } if (tr.target.ptr) { // We only have a weak reference on the target object, so we must first try to // safely acquire a strong reference before doing anything else with it. if (reinterpret_cast<RefBase::weakref_type*>( tr.target.ptr)->attemptIncStrong(this)) { error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this); } else { error = UNKNOWN_TRANSACTION; } } else { error = the_context_object->transact(tr.code, buffer, &reply, tr.flags); } //ALOGI("<<<< TRANSACT from pid %d restore pid %d sid %s uid %d\n", // mCallingPid, origPid, (origSid ? origSid : "<N/A>"), origUid); if ((tr.flags & TF_ONE_WAY) == 0) { LOG_ONEWAY("Sending reply to %d!", mCallingPid); if (error < NO_ERROR) reply.setError(error); // b/238777741: clear buffer before we send the reply. // Otherwise, there is a race where the client may // receive the reply and send another transaction // here and the space used by this transaction won't // be freed for the client. buffer.setDataSize(0); constexpr uint32_t kForwardReplyFlags = TF_CLEAR_BUF; sendReply(reply, (tr.flags & kForwardReplyFlags)); } else { if (error != OK) { std::ostringstream logStream; logStream << "oneway function results for code " << tr.code << " on binder at " << reinterpret_cast<void*>(tr.target.ptr) << " will be dropped but finished with status " << statusToString(error); // ideally we could log this even when error == OK, but it // causes too much logspam because some manually-written // interfaces have clients that call methods which always // write results, sometimes as oneway methods. if (reply.dataSize() != 0) { logStream << " and reply parcel size " << reply.dataSize(); } std::string message = logStream.str(); ALOGI("%s", message.c_str()); } LOG_ONEWAY("NOT sending reply to %d!", mCallingPid); } mServingStackPointer = origServingStackPointer; mCallingPid = origPid; mCallingSid = origSid; mCallingUid = origUid; mHasExplicitIdentity = origHasExplicitIdentity; mStrictModePolicy = origStrictModePolicy; mLastTransactionBinderFlags = origTransactionBinderFlags; mWorkSource = origWorkSource; mPropagateWorkSource = origPropagateWorkSet; IF_LOG_TRANSACTIONS() { std::ostringstream logStream; logStream << "BC_REPLY thr " << (void*)pthread_self() << " / obj " << tr.target.ptr << ": \t" << reply << "\n"; std::string message = logStream.str(); ALOGI("%s", message.c_str()); } } break; case BR_DEAD_BINDER: { BpBinder *proxy = (BpBinder*)mIn.readPointer(); proxy->sendObituary(); mOut.writeInt32(BC_DEAD_BINDER_DONE); mOut.writePointer((uintptr_t)proxy); } break; case BR_CLEAR_DEATH_NOTIFICATION_DONE: { BpBinder *proxy = (BpBinder*)mIn.readPointer(); proxy->getWeakRefs()->decWeak(proxy); } break; case BR_FINISHED: result = TIMED_OUT; break; case BR_NOOP: break; case BR_SPAWN_LOOPER: mProcess->spawnPooledThread(false); break; default: ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd); result = UNKNOWN_ERROR; break; } if (result != NO_ERROR) { mLastError = result; } return result; } 这段代码怎么理解
最新发布
11-26
<think> 首先,用户要求用中文回答问题,然后根据问题和回答提出3-5个相关问题。问题必须放在回答末尾,第一行必须是"§§相关问题§§",不能换行分散。 用户提供的代码是Android Binder IPC框架中的`IPCThreadState::executeCommand`方法实现。我需要解释这段代码的功能和关键点。 ### 理解代码 这段代码处理Binder驱动发送的命令(BR_*命令)。每个命令对应不同的操作,如引用计数管理、事务处理、死亡通知等。 关键部分: 1. **命令分发**:基于`cmd`参数,使用switch-case处理不同命令。 2. **引用计数命令**: - BR_ACQUIRE:增加强引用计数,并回复BC_ACQUIRE_DONE。 - BR_RELEASE:减少强引用计数,将对象推入待处理队列(mPendingStrongDerefs)。 - BR_INCREFS/BR_DECREFS:处理弱引用计数。 3. **事务处理**: - BR_TRANSACTION:处理跨进程调用。读取事务数据,设置调用上下文,调用目标对象的transact方法,并发送回复(如果不是单向调用)。 4. **其他命令**: - BR_DEAD_BINDER:处理Binder对象死亡通知。 - BR_SPAWN_LOOPER:创建新的线程池线程。 - 错误处理和默认情况。 核心逻辑是处理驱动发送的命令,维护对象生命周期,并执行远程方法调用。 ### 构建回答 - **开头总结**:简要说明代码作用。 - **详细解释**:分点解释主要命令的处理逻辑。 - **关键点强调**:如事务处理流程、引用计数管理、线程池扩展。 - **结尾**:确保回答完整。 ### 相关问题 根据代码内容,提出3-5个相关问题: 1. BR_TRANSACTION和BR_TRANSACTION_SEC_CTX的区别是什么? 2. 为什么在BR_RELEASE中不直接释放对象而是推入队列? 3. mPendingStrongDerefs和mPendingWeakDerefs的作用是什么? 4. 在事务处理中,为什么需要保存和恢复调用上下文? 5. BR_SPAWN_LOOPER如何触发新线程创建? 选择3-5个最相关的。 ### 输出格式 - 回答内容用中文。 - 末尾输出"§§相关问题§§",后跟问题列表。 - 问题用数字编号。 </think>这段代码是 Android Binder IPC 框架的核心方法 `IPCThreadState::executeCommand`,用于处理 Binder 驱动发送的各种命令(以 `BR_` 开头的指令)。它负责管理跨进程通信中的对象生命周期、事务处理和线程调度。以下是关键逻辑的解析: --- ### 一、核心结构解析 1. **方法签名** `status_t IPCThreadState::executeCommand(int32_t cmd)`: - 参数 `cmd` 是 Binder 驱动下发的命令(如 `BR_TRANSACTION`、`BR_ACQUIRE`)。 - 返回值 `status_t` 表示执行状态(如 `NO_ERROR`、`TIMED_OUT`)。 2. **智能指针与对象引用** - `BBinder* obj`:指向 Binder 本地对象的指针。 - `RefBase::weakref_type* refs`:弱引用管理对象,用于安全访问 `BBinder`。 - 通过 `mIn.readPointer()` 从驱动读取对象指针。 --- ### 二、关键命令处理逻辑 #### (1) **引用计数管理命令** | 命令 | 行为 | 响应驱动 | |----------------|----------------------------------------------------------------------|-----------------------| | **`BR_ACQUIRE`** | 增加强引用计数 (`obj->incStrong()`) | 回复 `BC_ACQUIRE_DONE` | | **`BR_RELEASE`** | 将强引用释放操作延迟到安全点(推入 `mPendingStrongDerefs` 队列) | 无直接响应 | | **`BR_INCREFS`** | 增加弱引用计数 (`refs->incWeak()`) | 回复 `BC_INCREFS_DONE` | | **`BR_DECREFS`** | 将弱引用释放操作推入 `mPendingWeakDerefs` 队列 | 无直接响应 | #### (2) **事务处理命令** - **`BR_TRANSACTION` / `BR_TRANSACTION_SEC_CTX`**: 1. 读取事务数据(`binder_transaction_data`),封装为 `Parcel` 对象 `buffer`。 2. 保存当前线程上下文(如 PID、UID),替换为发送方上下文。 3. **执行跨进程调用**: ```cpp error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer, &reply, tr.flags); ``` 4. 若非单向调用(`!TF_ONE_WAY`),通过 `sendReply()` 返回结果。 5. 恢复原始线程上下文。 #### (3) **其他关键命令** - **`BR_ATTEMPT_ACQUIRE`**:尝试增加强引用(非阻塞),回复成功/失败状态。 - **`BR_DEAD_BINDER`**:处理 Binder 对象死亡通知(`proxy->sendObituary()`)。 - **`BR_SPAWN_LOOPER`**:创建新的线程池线程(`mProcess->spawnPooledThread(false)`)。 - **`BR_FINISHED`**:返回 `TIMED_OUT`,触发线程退出(见 `joinThreadPool` 超时逻辑)。 --- ### 三、设计要点 1. **延迟释放机制** - `BR_RELEASE`/`BR_DECREFS` 不立即释放对象,而是推入 `mPendingStrongDerefs`/`mPendingWeakDerefs` 队列,在 `processPendingDerefs()` 中批量处理(避免并发问题)。 2. **上下文切换** - 事务处理时保存/恢复 `mCallingPid`、`mCallingUid` 等,确保权限检查正确。 3. **错误隔离** - 错误码过滤(如允许 `TIMED_OUT` 但禁止其他错误),避免无关错误终止进程。 4. **资源扩展** - `BR_SPAWN_LOOPER` 动态创建新线程应对高负载(见线程池设计)。 --- ### 四、线程安全与性能 - **无锁设计**:命令处理无全局锁,依赖 Binder 驱动的单线程命令队列。 - **批量处理**:引用计数变更聚合到队列,减少驱动交互次数。 - **异步优化**:单向调用(`TF_ONE_WAY`)不等待回复,直接丢弃结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值