星期五, 12月 25, 2009

windows的 stack、heap記憶體(內存)管理重點筆記

1/ windows的flat 模式: 這題目要講起來可以很深,包含許多的組合語言的東西。但在此我只想說一個結果,就是因為windows是使用這樣的一個記憶體管理位址模式,所以使得每個process都可以有私有的4G的「定址」能力,但因為windows當初要相容MIPS R4000 architecture,所以高位址的2G部份放的是kernel code,而我們的ap只能用低部份的2G,所以正確的來講,我們的程式能夠使用2G的定址能力。

2/虛擬記憶體: 在80386處理器後,cup support 保護模式,paging 模式。我們都知道windows會使用硬碟來充當ram使用,當ram不足的時候。這就是用paging的cpu功能。有了這個功能,os就可以讓每個process都可以使用2G的data,即使ram只有幾MB。在標題1我們有提到「定址」的這個詞,這只是說cpu的register(暫存器)有能力讓我們定出那麼大的空間。但是可以定出那麼大麼大的空間並不表示你一定先要有那麼大的ram在電腦上。定址是一回事,配置(allocate)又是另一回事,但二者都很重要。比如在dos 80286前的時代,有所謂的640k的限制(那是指定址能力先天不足),所以你就算是買了4MB的ram插在電腦上,還是浪費。回到主題,因為386以後有paging的能力,加上register是32位元,所以就組合出一種相當完美的記憶體管理方法: 每個process都有虛擬的4G記憶體,且可以真的使用到4G,即使你的ram沒有4G,windows會把你的虛擬記憶體資料放到硬碟上。為何說是「虛擬」?就是指你不一定真的有那麼多的真實的ram。比如說你真實的ram有128MB,而你的程式超大,用到512MB,那麼當程式在跑的時候,只會把正需要的code往128MB的ram上放,而把尚不用的放(paging)在硬碟上。

3/ stack: 何謂stack? 是用來放function上auto級的變數(這樣的說法較專業),所謂auto級的就是變數是宣告在function內,它的生命(life time/ extent)在function結束後就無效了! stack的大小是由 linker來決定,以bcb為例,最大可以到0x1000000,即約16MB,你可以在project option上改。由多程式人員喜歡把object放在stack上,即用下面的宣告方式
ClassT object; 這樣整個object的資料都會配在stack上,若class小還好,大則容易overflow。故一般建議用new的方式來create objcet,只留下4byte的指標在stack上。又如這些天許多玩matalab的人問到2維array overflow的問題,也是因為把array宣告在stack上所造成。要解決的方式還是一樣,把它用new的方式create到heap上(稍後會講)。但二維的動態產生array需要一些技巧,可查一下我的文章。還有,使用recursive function的人也要特別注意overfolw的問題。必要的話可以改寫演算法不要用遞回。stack的使用很方便,因為不用僅管使用,無需去自行清理,唯不要overflow就很棒!

4/ heap: 是用來動態使用記憶體的方式,使用的自由度最高,但需要自行善後清理。通常是用malloc/free或是new/delete來處理。heap在windows下可以分為二種,1為default heap2為dynamic heap。default heap 可以是windows dll 等api使用,也可以app自己使用。我們開發的ap是如何來使用這個default heap呢? 可透過下面的三個api來使用GlobalAlloc 或 LocalAlloc 或GetProcessHeap來使用。事實上這個heap還再細分為fixed和movable二種。一般我們都是使用fixed。而vc++的malloc等c run time就是用這個default heap。這個default heap的大小限制為何? 這是一個很重要的題目,我們下個主題講。另一種heap稱為 dynamic heap,這個heap就全然是我們的ap自由使用的地方。它和default heap有個不同? dynamic heap 全都是自己程式用,沒有別的api使用,另外還有一個重要的地方是這個heap可以控制多緒(multithread)同步共享heap的管理。可由HeapCreate等相關api還有VirtualXxx api來建立。bcb本身的malloc等c run time 聽說是使用這種heap,與vc++有所不同。

5/heap size(一): 這是一個很重要的題目。到底 heap size的限制為何? 答案是… 無論是dynamic 或是 defualt heap都是限制在定址能力上,即以windwos來說,就是2G。但是奇怪了,project option的linker選項中有提到一個heap size的地方,就像stack也在那設定一樣。而這個選項裡的最大值一樣只能到0x1000000,即16MB左右。而實際上許多人都曾在程式中要求超過百mb以上的heap,怎都沒事?? 而這個設定值有啥用? 答案是 : 所謂的min size的值是指commit的值,max size是reserve的值。commit / reserve這二個詞在windows api 與vc++中常用。我大概講一下…所謂的reserve是指程式可以「要求註冊」保留虛擬位址的大小。請注意是「虛擬位址」,比個喻,就像是先向政府預定門牌號1-100號都將是我家所用,但還沒建好房子。而commit size則是每次我建房子都是以幾個門牌為單位建立,比如說,commit=4,即表每次都以4間房子來建,直到100個門牌都用完。所有windows的記憶管理都是用reserve/commit的方式在處理。都是先要求將有多少位址會用到,然後等實值用到時再依commit的大小來一單位一單位的分配實值記憶體給你用。

6/ heap size (二) : 之前有提到像vc++ 的malloc都是用heap。最早我說它的限制是2G,但剛在上面又說linker設定上只能最大是16mb,若真的是16mb,那malloc早就應該overflow n次了,很茅盾! 事實上… heap的大小是真的限制在2G,即使用都不去改option中的值,它還是2G。哇~~那那設定是假的? 不…那設定正確講是為了效能。怎說呢? 雖然最大可使用是2G,但windows並非一開始就拿2G等著你用。它是在需要的時候先行要求位址(門牌),在一一的配給你。在option上設定就好比你打電話去餐聽先定位,先定個15個位子(reserve size),並且向服務生說我們會分批進去,而每批都是3個人為單位(commit size)。服務人員想講完電話後想…我們這個時間的生意這麼好,若事先就空著15個位子,那就少賺了…於是先空3個位子,反正每一批都是3人來。於是第一批到後,餐廳再空3人位子出來等,直到15人都到了! 這種預先定位的好處就是你進去餐廳後不必多廢話,進去就入座! 很有效能!

7/ heap size(三): 把剛的比喻故事延申下去…萬一我臨時又有6個朋友也要一起去吃飯,而我剛只定了15位,餐廳能否再開6位給我呢? 當然沒問題! 只是餐聽的人員說,你要稍等一下,等我再補登記新人數後再配位子入座! 所以事實上defult heap 非靜態的只到你reserve的大小就停了,它可以再自動的變大,只是需要一點時間和資源。記住! 是可以到2G沒問題的! 而從這比喻中你應該可以了解,若是開始的時候我們就正確的預定好人數,就不會多花一點時間補登記。反過來說,即使亂預定也沒關係,都還是有位子可以座,只是要多補n次的登記時間!

8/ 何時該使用default heap,何時用dynamic heap? 這問題其實不是很重要,為了portable,用malloc/ new來處理就好,compiler會選用其中一種來處理。除了在開發multithead的程式時,當你不希望主thread中的heap被二個以上的thead同時存取,你可以用dynamic heap來建立,即用HeapCreate( )的預設建立方法。當然你也可以用這個function建立出一般的fixed的heap,只要將參數1改為HEAP_NO_SERIALIZE,就可以!


9/ 補一下commit值的重要性,若每次你new的東西是很大的,而你把commit值又設很小,那麼每new一次就要補手續n次。比如說每次要new 40k 的資料,但你commit只設4k,那…new一次就配置手續10次。當然,若你說把commit設成100k,那麼一次就搞定,但…也有個小缺點 : 剩下的配給你的真實的60k浪費在那裡了。給別的process用那60k不好嗎? 所以…設成40-50k是不是比較折衷的好設定呢?!

轉貼作者: 蕭沖 qs.xiao@gmail.com
http://delphi.ktop.com.tw/board.php?cid=168&fid=912&tid=83727

星期一, 12月 21, 2009

Webclient Using Python

Http GET

>>> import httplib
>>> conn = httplib.HTTPConnection("www.python.org")
>>> conn.request("GET", "/index.html")
>>> r1 = conn.getresponse()
>>> print r1.status, r1.reason
200 OK
>>> data1 = r1.read()
>>> conn.request("GET", "/parrot.spam")
>>> r2 = conn.getresponse()
>>> print r2.status, r2.reason
404 Not Found
>>> data2 = r2.read()
>>> conn.close()

Http Request

>>> import httplib, urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> headers = {"Content-type": "application/x-www-form-urlencoded",
... "Accept": "text/plain"}
>>> conn = httplib.HTTPConnection("musi-cal.mojam.com:80")
>>> conn.request("POST", "/cgi-bin/query", params, headers)
>>> response = conn.getresponse()
>>> print response.status, response.reason
200 OK
>>> data = response.read()
>>> conn.close()

星期四, 12月 17, 2009

Sql In

使用Sql In 找出自已好友所建立的事件列表

SELECT     UserDataUniversitySchool, UserDataDepartment, UserDataSex, UserDataPhoto, EventDataName, EventDataEstablishDate, 
EventDataAssemblePosition, EventDataID, EventDataUID, UserDataNickName
FROM         dbo.vw_EventDataTimeLine
WHERE     (EventDataUID IN (SELECT UserFriendsAddUID FROM dbo.vw_FriendsShipDetail WHERE (UserFriendsUID = @uid) AND (UserFriendsIsConfirm = 1)))

星期三, 12月 16, 2009

C# 取得目前時間為星期幾

DateTime.DayOfWeek 屬性

DayOfWeek 列舉的常數,表示一週天數。
這個屬性值的範圍從 0 開始 (表示星期日) 到 6 (表示星期六)

  DateTime dt = new DateTime(2009, 12, 17);
  string tmp = dt.DayOfWeek.ToString();//tmp = Thursday
  string tmp2 = dt.DayOfWeek.ToString("d");//tmp2 = 4 

星期二, 12月 15, 2009

Backup System Using tar


backup:
cd /mnt/linux && tar -jcvf /mnt/bak/linux.tar.bz2 *
restore:
tar -jxvpf /mnt/bak/linux.tar.bz2 -C /mnt/linux

/mnt/linux 備份目錄

星期一, 12月 14, 2009

PHP XML Receive


<?xml version="1.0" encoding="UTF-8"?>
<inventory>
<book>
<author>Nick Chase</author>
<title>XML Primer Plus</title>
<publisher>Sams</publisher>
</book>
<book>
<author>Earth</author>
<title>David Brin</title>
<publisher>Spectra</publisher>
</book>
<movie>
<director>Steven Spielberg</director>
<title>Raiders of the Lost Ark</title>
<actor>Harrison Ford</actor>
<actor>Karen Allen</actor>
</movie>
<movie>
<director>Rob Reiner</director>
<title>The American President</title>
<actor>Michael Douglas</actor>
<actor>Annette Bening</actor>
<actor>Martin Sheen</actor>
</movie>
</inventory>


if (!isset($HTTP_RAW_POST_DATA))
$HTTP_RAW_POST_DATA = file_get_contents("php://input");

header("Content-type: text/plain");
echo $HTTP_RAW_POST_DATA;
?>



if (!isset($HTTP_RAW_POST_DATA))
$HTTP_RAW_POST_DATA = file_get_contents("php://input");

$doc = new DOMDocument();
$doc->loadXML($HTTP_RAW_POST_DATA);

$allBooks = $doc->getElementsByTagName('book');
$numBooks = $allBooks->length;

$allMovies = $doc->getElementsByTagName('movie');
$numMovies = $allMovies->length;

echo "There are ".$numBooks." books and ".$numMovies." movies.";
?>

acer Ferrari 1100 wifi setting

1. 安裝 ndiswrapper
2. 安裝 bcmwl5.inf
3.
sudo modprobe -r b43 b44 ssb wl
sudo modprobe wl
sudo modprobe b44
sudo /etc/init.d/networking restart
sudo iwlist scan

星期六, 12月 12, 2009

FCKEditor Asp.net

原本使用.net ajaxcontroltoolkit內的editor元件,
由於頁面會載入太多東西,簡單來說就是太肥,
於是找了網上大家最常用的FCKEditor,還有一些優化方法。
可參考以下二篇教學
Reference:
FCKeditor 超強html線上編輯器應用於ASP.NET
ASP Fckeditor 優化技巧教學

星期三, 12月 09, 2009

用PHP 做HTTP Request


$fields = array(
'__VIEWSTATE'=>'0IZf2tvjZxs7aeq7Tx7mFkZBB62iWgsCq3zbL%2BTnYZZ%2FXfeXgvDJNEEd3b3Z7COD',
'__EVENTVALIDATION'=>'YAJy6SEjjCbcu4df21JN%2BhAtGvApqKxJhDeS%2FE5s24EVBRHYEIqypa9hS%2BdTo%2FS%2F%2By8GO8Zu%2FS0%3D',
'Login1%24UserName'=>urlencode($StuNo),
'Login1%24Password'=>urlencode($StuPwd),
'Login1%24LoginButton'=>'%E7%99%BB%E5%85%A5'

);//POST的東西

foreach($fields as $key=>$value)
{

$fields_string .= $key.'='.$value;
if(sizeof($fields)-1!=$count)
$fields_string.="&";

}//組成POST STRING

$curl = curl_init("YOUR REQUEST URL");
$ckfile = tempnam ("/tmp", "CURLCOOKIE");//建立Cookie文件
curl_setopt($ch, CURLOPT_COOKIEJAR, "./cookie.txt");//寫入指定的Cookie
curl_setopt($curl, CURLOPT_POST, 1);//post資料給指定網頁
curl_setopt($curl, CURLOPT_POSTFIELDS, $fields_string);
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.2; zh-TW; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5");//UserAgent
$Result = curl_exec($curl);//Html String
curl_close($curl);

星期日, 12月 06, 2009

使用mysqldump

mysqldump最常見的用法是:

shell>; mysqldump --opt -u user --password="password" db_name >; backup-file.sql
或者壓縮備份文件:
#mysqldump --opt -u user --password="password" database | bzip2 -c >; database.sql.bz2

在dbname已經存在的情況下,讀入備份文件恢復數據庫,

shell>; mysql db_name < backup-file.sql (備註:建議使用--database選項)

或者

shell>; mysql -e "source /path-to-backup/backup-file.sql" db_name

mysqldump 還可以用於在兩個mysql server之間複製數據:

shell>; mysqldump --opt db_name | mysql --host=remote_host -C db_name

也可以同時備份多個數據庫:

shell>; mysqldump --databases db_name1 [db_name2 ...] >; my_databases.sql

如果想一次備份整個數據庫使用 --all-databases 選項:

shell>; mysqldump --all-databases >; all_databases.sql




常見選項:
--add-drop-table:添加DROP TABLE語句
--add-locks:用LOCK TABLES 和 UNLOCK TABLES 語句封裝插入每個表格的語句,能加速數據導入速度
--all-databases, -A: 備份所有數據庫
--compress, -C:用於在兩個server之間複製時壓縮數據
--databases, -B: 用於備份多個數據庫,如果沒有該選項,mysqldump 把第一個名字參數作為數據庫名,後面的作為表名。使用該選項,mysqldum把每個名字都當作為數據庫名。CREATE DATABASE IF NOT EXISTS db_name and USE db_name 會被添加到導出文件裡。
--force, -f:即使發現sql錯誤,仍然繼續備份
--host=host_name, -h host_name:備份主機名,默認為localhost
--no-data, -d:只導出表結構
--opt:等同於激活--add-drop-table --add-locks --create-options --disable-keys --extended-insert --lock-tables --quick --set-charset這些選項
--password[=password], -p[password]:密碼
--port=port_num, -P port_num:制定TCP/IP連接時的端口號
--protocol={TCP | SOCKET | PIPE | MEMORY}:制定連接所用的協議
--quick, -q:快速導出
--socket=path, -S path:當連接至localhost時,制定socket文件
--tables:覆蓋 --databases or -B選項,後面所跟參數被視作表名
--user=user_name, -u user_name:用戶名
--xml, -X:導出為xml文件

[Asp.Net] master page 事件處理順序

1.主版頁面控制項 Init 事件。
2.內容控制項 Init 事件。
3.主版頁面 Init 事件。
4.內容頁面 Init 事件。

5.內容頁面 Load 事件。
6.主版頁面 Load 事件。

7.內容控制項 Load 事件。
8.內容頁面 PreRender 事件。
9.主版頁面 PreRender 事件。
10.主版頁面控制項 PreRender 事件。
11.內容控制項 PreRender 事件。

處理查詢運算式中的例外狀況


class ExceptionsOutsideQuery
{
static void Main()
{
// DO THIS with a datasource that might
// throw an exception. It is easier to deal with
// outside of the query expression.
IEnumerable<int> dataSource;
try
{
dataSource = GetData();
}
catch (InvalidOperationException)
{
// Handle (or don't handle) the exception
// in the way that is appropriate for your application.
Console.WriteLine("Invalid operation");
goto Exit;
}

// If we get here, it is safe to proceed.
var query = from i in dataSource
select i * i;

foreach (var i in query)
Console.WriteLine(i.ToString());

//Keep the console window open in debug mode
Exit:
Console.WriteLine("Press any key to exit");
Console.ReadKey();
}

// A data source that is very likely to throw an exception!
static IEnumerable<int> GetData()
{
throw new InvalidOperationException();
}
}

LINQ 查詢運算式


class LINQQueryExpressions
{
static void Main()
{

// Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 };

// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;

// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}

Using LINQ To Create Custom Datatable And Travel Table


IEnumerable<DataRow> SubenumTable =
from goodTable in dt.AsEnumerable()
where goodTable.Field<string>("TravelRegion") == row.col1.ToString()
select goodTable;
//sr.Append(row.col1.ToString()+"<br>");
foreach (DataRow goodsrow in SubenumTable)
{


SiteNode Subn1 = new SiteNode();
Subn1.ParentID = count.ToString();
Subn1.ID = goodsrow["TravelID"].ToString();
Subn1.Title = goodsrow["TravelAttractions"].ToString();
Subn1.Pos = goodsrow["TravelLat"].ToString() + "," + goodsrow["TravelLng"].ToString();
nodes.Add(Subn1);
}

使用 LINQ 擷取 dataTable 部份列數的寫法

IEnumerable<DataRow> source = dt.AsEnumerable().Take((this.page) * pageSize);

Creating a Custom CopyToDataTable Method



// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];
DataTable details = ds.Tables["SalesOrderDetail"];

var query =
from order in orders.AsEnumerable()
join detail in details.AsEnumerable()
on order.Field<int>("SalesOrderID") equals
detail.Field<int>("SalesOrderID")
where order.Field<bool>("OnlineOrderFlag") == true
&& order.Field<DateTime>("OrderDate").Month == 8
select new
{
SalesOrderID =
order.Field<int>("SalesOrderID"),
SalesOrderDetailID =
detail.Field<int>("SalesOrderDetailID"),
OrderDate =
order.Field<DateTime>("OrderDate"),
ProductID =
detail.Field<int>("ProductID")
};

DataTable orderTable = query.CopyToDataTable();

Creating a DataTable From a Query


dataGridView.DataSource = bindingSource;

// Fill the DataSet.
DataSet ds = new DataSet();
ds.Locale = CultureInfo.InvariantCulture;
FillDataSet(ds);

DataTable orders = ds.Tables["SalesOrderHeader"];

// Query the SalesOrderHeader table for orders placed
// after August 8, 2001.
IEnumerable<DataRow> query =
from order in orders.AsEnumerable()
where order.Field<DateTime>("OrderDate") > new DateTime(2001, 8, 1)
select order;

// Create a table from the query.
DataTable boundTable = query.CopyToDataTable<DataRow>();

// Bind the table to a System.Windows.Forms.BindingSource object,
// which acts as a proxy for a System.Windows.Forms.DataGridView object.
bindingSource.DataSource = boundTable;

星期四, 12月 03, 2009

mstsc 指令

mstsc /console 會連到session 0
意即跟遠端電腦同一個畫面,
不會新開一個登入帳號,
但windows server 都會新開一個session。
改用mstsc /admin即可連到session 0
PS:mstsc 開啟遠端連線,連xp與vista都也是連session 0

PHP XML Build


<?php
$doc = new DOMDocument('1.0', 'UTF-8');

$root = $doc->createElement('songs');
$doc->appendChild($root);

for($i=0;$i<10;$i++){

$root_child = $doc->createElement('song');
$root->appendChild($root_child);

$root_attr1 = $doc->createAttribute('url');
$root_child->appendChild($root_attr1);

$root_text = $doc->createTextNode('This is the root element!');
$root_attr1->appendChild($root_text);

$root_attr2= $doc->createAttribute('artist');
$root_child->appendChild($root_attr2);

$root_text = $doc->createTextNode('This is the root element!');
$root_attr2->appendChild($root_text);

$root_attr3 = $doc->createAttribute('track');
$root_child->appendChild($root_attr3);

$root_text = $doc->createTextNode('This is the root element!');
$root_attr3->appendChild($root_text);

}

print $doc->saveXML();
?>

星期三, 12月 02, 2009

C# 取得本機ip

string strHostIP = "";
IPHostEntry oIPHost = Dns.GetHostEntry(Environment.MachineName);
if (oIPHost.AddressList.Length > 0)
{
strHostIP = oIPHost.AddressList[0].ToString();
}

Asp.net Regex.Matches

在parser html時使用正則表示式當然是最方便不過了,
如果再加上groups使用就便方便!!,用括號來分割你要的group
html content :
<span id="ctl00_ContentPlaceHolder1_ctl00_FormView1_preschoolLabel">市立中正高工</span>
註:\s+表示空白間隔
Mathc = Regex.Matches(profileHtml, "<span\\s+id=\"(ctl00_ContentPlaceHolder1_ctl00_FormView1.*)\">(.*)</span>");
for (int i = 0; i < Mathc.Count; i++)
{
//get regex group 
string g1 = Mathc[i].Groups[1].Value;
//ctl00_ContentPlaceHolder1_ctl00_FormView1_preschoolLabel
string g2 = Mathc[i].Groups[2].Value; 
//市立中正高工
}

星期二, 12月 01, 2009

[jQuery API] div 左右分割長短腳的問題

#divContainer
{
float:left;
width:400px;
height:auto;
overflow:inherit;
}

#divLeft
{
width:200px; float:left;
}

#divRight
{
width:200px; float:right;
}


$("#divRight , #divLeft").css("height", Math.max($("#divRight ").height(), $("#divLeft").height()));

Reference:
網頁教學-解決Div排版長短腳的問題

uploadify session null

uploadify flash 本身上傳自己的 session 和 browser 不會共用,
: 就連 user agnet 名稱也不同,所以會有登入驗證失敗的問題。
: 這部份的解法不會太難:
: 1. 新增一個資料表裡面有一個 hashkey 對應 user_id, album_id 之類的欄位
: 2. 每次上傳的時候,先新增一個 hashkey, user_id 及其它你需要的資料
: 3. 當上傳的時候,取回剛剛新增的 hashkey 一併然後 post 到妳的 controller 裡面
: 4. 根據 hashkey 去找 user_id..等等,加上上傳的照片路徑(或照片),插入新資料
: 5. 上傳完畢。
: 這是一個簡單的解法,很有用。

Reference[分享]CakePHP+uploadify => Ajax uploader