導航:首頁 > 編程系統 > linuxsuspended

linuxsuspended

發布時間:2023-02-08 06:26:58

A. linux觸摸屏驅動中什麼時候會調用suspend這個函數

android系統摁下電源鍵後會讓系統進入休眠以達到節電的目的。內核驅動中和休眠相關的就是suspend和resume函數。

suspend函數用於休眠,resume函數用於喚醒。下面分析驅動中的這兩個函數是如何被調用到的。

驅動部分:

首先需要分析驅動的注冊過程,較新的內核都是採用DTS方式來取代在內核中直接定義platform_device數據結構的注冊方式,本文是基於DTS機制的內核來分析。

proct對應的dts文件在編譯時被編譯為dtb文件,uboot在啟動時候會將其地址傳給內核,內核在啟動過程中會去解析,具體解析是在start_kernel()->setup_arch() --> unflatten_device_tree()中具體分析可以參考網上,解析的最終結果會存放在allnodes地址處,這個allnodes隨後在machine的init函數
中被使用,init函數中會根據allnodes中的節點數據組合成platform_device數據結構,然後將其注冊到platform匯流排上,下面簡要分析一下並重點關注這些初始化過程中和
pm相關的初始化。

我參與的項目中machine的init函數就是via_init_machine函數,在這個函數中就是調用了of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL)這個函數來解析allnodes的。of_platform_populate是系統提供的介面。下面分析這個介面的實現:

[html] view plain
int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent)
{
struct device_node *child;
int rc = 0;

root = root ? of_node_get(root) : of_find_node_by_path("/");
if (!root)
return -EINVAL;

for_each_child_of_node(root, child) {
rc = of_platform_bus_create(child, matches, lookup, parent, true);
if (rc)
break;
}

of_node_put(root);
return rc;
}
root最後就是取到的根節點,然後其作為參數傳遞給of_platform_bus_create,of_platform_device_create_pdata的實現如下:

[html] view plain
static int of_platform_bus_create(struct device_node *bus,
const struct of_device_id *matches,
const struct of_dev_auxdata *lookup,
struct device *parent, bool strict)
{
const struct of_dev_auxdata *auxdata;
struct device_node *child;
struct platform_device *dev;
const char *bus_id = NULL;
void *platform_data = NULL;
int rc = 0;

/* Make sure it has a compatible property */
if (strict && (!of_get_property(bus, "compatible", NULL))) {
pr_debug("%s() - skipping %s, no compatible prop\n",
__func__, bus->full_name);
return 0;
}

auxdata = of_dev_lookup(lookup, bus);
if (auxdata) {
bus_id = auxdata->name;
platform_data = auxdata->platform_data;
}

if (of_device_is_compatible(bus, "arm,primecell")) {
of_amba_device_create(bus, bus_id, platform_data, parent);
return 0;
}

dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
if (!dev || !of_match_node(matches, bus))
return 0;

for_each_child_of_node(bus, child) {
pr_debug(" create child: %s\n", child->full_name);
rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
if (rc) {
of_node_put(child);
break;
}
}
return rc;
}
根據傳入參數,我們這里直接分析of_platform_device_create_padate函數,如下:

[html] view plain
struct platform_device *of_platform_device_create_pdata(
struct device_node *np,
const char *bus_id,
void *platform_data,
struct device *parent)
{
struct platform_device *dev;

if (!of_device_is_available(np))
return NULL;

dev = of_device_alloc(np, bus_id, parent);
if (!dev)
return NULL;

#if defined(CONFIG_MICROBLAZE)
dev->archdata.dma_mask = 0xffffffffUL;
#endif
dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
dev->dev.bus = &platform_bus_type;
dev->dev.platform_data = platform_data;

/* We do not fill the DMA ops for platform devices by default.
* This is currently the responsibility of the platform code
* to do such, possibly using a device notifier
*/

if (of_device_add(dev) != 0) {
platform_device_put(dev);
return NULL;
}

return dev;
}

of_platform_device_create_padate->of_device_alloc->platform_device_alloc

便在platform_device_alloc函數中進行進行alloc和初始化了,實現如下:

[html] view plain
struct platform_device *platform_device_alloc(const char *name, int id)
{
struct platform_object *pa;

pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL);
if (pa) {
strcpy(pa->name, name);
pa->pdev.name = pa->name;
pa->pdev.id = id;
device_initialize(&pa->pdev.dev);
pa->pdev.dev.release = platform_device_release;
arch_setup_pdev_archdata(&pa->pdev);
}

return pa ? &pa->pdev : NULL;
}
可以看到有個device_initialize,這裡面對pdev.dev做一些列的初始化,其中有一個函數就是device_pm_init,這個函數就是我們一直關心的device相關的pm函數,具體實現如下:

[html] view plain
void device_pm_init(struct device *dev)
{
dev->power.is_prepared = false;
dev->power.is_suspended = false;
init_completion(&dev->power.completion);
complete_all(&dev->power.completion);
dev->power.wakeup = NULL;
spin_lock_init(&dev->power.lock);
pm_runtime_init(dev);
INIT_LIST_HEAD(&dev->power.entry);
dev->power.power_state = PMSG_INVALID;
}

可以看見它對device和功耗相關的數據做了一些初始化,我們這里先重點關注下dev->power.entry,初始化一個鏈表頭,所以他/它很有可能會在後面加到某個鏈表裡面去,而那個鏈表應該是用來保存所有的device用的。系統中所有的platform_device都是通過這種方式注冊到系統中的,那麼應該所有的platform_device都會初始化一個dev->power.entry,如果到時候把所有的dev->power.entry都添加到某個鏈表上去,那麼系統到時候查詢的時候只要找到這個list head就可以找到所有的platform_device了。嗯,不過這是我們的猜測。我們接下去分析來驗證下。

platform_device通過alloc之後已經初始化好了,那麼接下去就可以添加到系統中了,所以我們再回頭看of_platform_device_create_pdata的實現。
函數在of_device_alloc之後把dev->dev.bus賦值給了platform_bus_type,接著就調用了of_device_add函數,在of_device_add函數中最後通過device_add添加到了bus上,但是device_add中有個函數需要我們關系,就是device_pm_add(dev),實現如下:

[html] view plain
void device_pm_add(struct device *dev)
{
pr_debug("PM: Adding info for %s:%s\n",
dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
mutex_lock(&dpm_list_mtx);
if (dev->parent && dev->parent->power.is_prepared)
dev_warn(dev, "parent %s should not be sleeping\n",
dev_name(dev->parent));
list_add_tail(&dev->power.entry, &dpm_list);
dev_pm_qos_constraints_init(dev);
mutex_unlock(&dpm_list_mtx);
}

可以看到這里list_add_tail(&dev->power.entry, &dpm_list);這就驗證了我們之前的猜測。所有注冊到系統中的設備,最終都是會添加到dpm_list這條鏈表上。

那麼系統在休眠的時候是如何通過dmp_list這表鏈表來suspend設備的呢?接下去就是我們要分析的電源管理部分內容。

系統電源部分:
電源管理相關文件在kernel/power目錄下,前面已經分析到。系統中注冊的設備都是會添加到dmp_list這條鏈表上的。那麼睡眠的時候系統應該是會查找dmp_list這條鏈表,
然後通過這條鏈表依次去查到對應的driver,然後調用driver中的suspend方法。下面我們來驗證。

2.在suspend會輪詢bus下的driver,然後一次調用到driver->pm->suspend方法,然後進入休眠。

3.state_store->pm_suspend->enter_state->suspend_devices_and_enter->dpm_suspend_start->dpm_suspend->device_suspend->__device_suspend->pm_op->(ops->suspend)

B. linux執行命令停止無限彈

linux執行命令停止無限彈如下
先來寫一個需要一直運行的程序,比如 Flask 版的 Hello World$ vi hello.pyfrom flask import Flaskapp = Flask(__name__)pp.route('/') index():return hello world'if __name__ == '__main__':app.run(host=Ɔ.0.0.0') pip install flask$ python hello.p啟動成功控制台提示:* Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)此時打開瀏覽器訪問 http://你的伺服器ip:5000 即可看到 Hello World 了按 CTRL+C 退出,如果想讓程序一直運行又想同時做其他事怎麼辦?
CTRL+Z 暫停程序程序在前台運行時,按下 CRTL+Z, 程序進入暫停狀態[1] + 74237 suspended python hello.py此時你又可以在終端下敲其他命令了。但刷新瀏覽器,長時間沒有響應,因為程序進入暫停狀態了。jobs 列出後台運行的命$ jobs[1] - suspended python hello.py
再來啟動一個命令,比如$ tail -f hello.py然後 CTRL+Z 暫停,再運行下 jobs 命令前面的[1] [2] 是任務編號,+ - 和接下來要說的 fg、bg 命令有關,suspended 那一欄表示狀態,剩下的就是命令
要把一個程序放在後台運行,照上面的做法,得先運行,然後 CTRL+Z 暫停,再用 bg 命令放到後台運行。使用 & 來簡化這一過程,並且使用 > 來重定向後台運行的程序在終端上的輸出。

C. org.apache.catalina.startup.Bootstrap at localhost:50973

LDD(Linux Device Driver)第三章scull設備例子的時候,也遇到了相似的問題,後來發現是經make編譯出來的scull.ko的owner和group屬性不對,而一開始學習第二章hello world的時候卻沒有遇到這個問題,嘗試著chown和chgrp之後(own和group都改成root),就能夠順利地用insmod載入該模塊進內核了。

D. linux開機自動執行命令和腳本 自動啟動 自啟 進程一直運行

原文及更新: https://neucrack.com/p/91

直接在/etc/rc.local(/etc/rc.d/rc.local)文件中添加即可

上面這腳本實際上在使用時出現了問題, /home/neucrack/software/ss/start_ss_local.sh 這個命令始終沒有被執行,原因是 /home/neucrack/software/ss/start_kcptun_client.sh 中的命令阻塞了進程,導致後面一句始終沒有執行,可以將他們分別放到後台執行就行了,如何在後台執行可以看文章最後一部分

也可以自己手動在rc*.d中建立軟連接

桌面系統搜索 啟動 ,打開啟動管理器 添加刪除即可

一般有以下幾種方法:
1)在輸入命令的最前面加上 nohup 命令
如 nohup your_command & 這樣命令在你退出後仍然會在後台執行
2) setsid 命令
setsid your_command 該命令的結果是使你所運行的命令的父進程為init,所以只有關機該進程才會停止
3) (your_command &)
就是用括弧將你的命令括起來,這樣做也是使命令的父進程為init
4) disown
當你在命令行下輸入 your_command & 後命令就在後台執行了,然後執行jobs命令,該命令會列出當前正在後台執行的命令。例如輸入命令「top&」
然後執行"jobs"
輸出結果是
[1] + Suspended (tty output) top
注意行開頭方括弧內的數字,該數字叫做jobspec,是給當前後台運行的job的編號。這是你只要在命令行下輸入"disown -h 1" 後台運行的top命令就不會受到hangup信號的影響了。
5)使用 screen 命令
在命令行下輸入screen命令就開啟了一個screen進程,它就好像是一個全新的命令運行環境,在該環境中你可以像在正常的terminal下那樣執行
命令,但是這個screen是不受其父進程的hangup信號的影響的,既然screen不受其父進程影響,當你意外掉線或者退出系統時,在screen
中仍在執行的命令仍然會繼續執行。關於screen命令的使用方法你可以再去查閱相關資料。

E. 怎樣寫linux下的USB設備驅動程序

寫一個USB的驅動程序最 基本的要做四件事:驅動程序要支持的設備、注冊USB驅動程序、探測和斷開、提交和控制urb(USB請求塊)
驅動程序支持的設備:有一個結構體struct usb_device_id,這個結構體提供了一列不同類型的該驅動程序支持的USB設備,對於一個只控制一個特定的USB設備的驅動程序來說,struct usb_device_id表被定義為:
/* 驅動程序支持的設備列表 */
static struct usb_device_id skel_table [] = {
{ USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) },
{ } /* 終止入口 */
};
MODULE_DEVICE_TABLE (usb, skel_table);
對 於PC驅動程序,MODULE_DEVICE_TABLE是必需的,而且usb必需為該宏的第一個值,而USB_SKEL_VENDOR_ID和 USB_SKEL_PRODUCT_ID就是這個特殊設備的製造商和產品的ID了,我們在程序中把定義的值改為我們這款USB的,如:
/* 定義製造商和產品的ID號 */
#define USB_SKEL_VENDOR_ID 0x1234
#define USB_SKEL_PRODUCT_ID 0x2345
這兩個值可以通過命令lsusb,當然你得先把USB設備先插到主機上了。或者查看廠商的USB設備的手冊也能得到,在我機器上運行lsusb是這樣的結果:
Bus 004 Device 001: ID 0000:0000
Bus 003 Device 002: ID 1234:2345 Abc Corp.
Bus 002 Device 001: ID 0000:0000
Bus 001 Device 001: ID 0000:0000
得到這兩個值後把它定義到程序里就可以了。
注冊USB驅動程序:所 有的USB驅動程序都必須創建的結構體是struct usb_driver。這個結構體必須由USB驅動程序來填寫,包括許多回調函數和變數,它們向USB核心代碼描述USB驅動程序。創建一個有效的 struct usb_driver結構體,只須要初始化五個欄位就可以了,在框架程序中是這樣的:
static struct usb_driver skel_driver = {
.owner = THIS_MODULE,
.name = "skeleton",
.probe = skel_probe,
.disconnect = skel_disconnect,
.id_table = skel_table,
};
探測和斷開:當 一個設備被安裝而USB核心認為該驅動程序應該處理時,探測函數被調用,探測函數檢查傳遞給它的設備信息,確定驅動程序是否真的適合該設備。當驅動程序因 為某種原因不應該控制設備時,斷開函數被調用,它可以做一些清理工作。探測回調函數中,USB驅動程序初始化任何可能用於控制USB設備的局部結構體,它 還把所需的任何設備相關信息保存到一個局部結構體中,
提交和控制urb:當驅動程序有數據要發送到USB設備時(大多數情況是在驅動程序的寫函數中),要分配一個urb來把數據傳輸給設備:
/* 創建一個urb,並且給它分配一個緩存*/
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
retval = -ENOMEM;
goto error;
}
當urb被成功分配後,還要創建一個DMA緩沖區來以高效的方式發送數據到設備,傳遞給驅動程序的數據要復制到這塊緩沖中去:
buf = usb_buffer_alloc(dev->udev, count, GFP_KERNEL, &urb->transfer_dma);
if (!buf) {
retval = -ENOMEM;
goto error;
}

if (_from_user(buf, user_buffer, count)) {
retval = -EFAULT;
goto error;
}
當數據從用戶空間正確復制到局部緩沖區後,urb必須在可以被提交給USB核心之前被正確初始化:
/* 初始化urb */
usb_fill_bulk_urb(urb, dev->udev,
usb_sndbulkpipe(dev->udev, dev->bulk_out_endpointAddr),
buf, count, skel_write_bulk_callback, dev);
urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
然後urb就可以被提交給USB核心以傳輸到設備了:
/* 把數據從批量OUT埠發出 */
retval = usb_submit_urb(urb, GFP_KERNEL);
if (retval) {
err("%s - failed submitting write urb, error %d", __FUNCTION__, retval);
goto error;
}
當urb被成功傳輸到USB設備之後,urb回調函數將被USB核心調用,在我們的例子中,我們初始化urb,使它指向skel_write_bulk_callback函數,以下就是該函數:
static void skel_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
{
struct usb_skel *dev;

dev = (struct usb_skel *)urb->context;

if (urb->status &&
!(urb->status == -ENOENT ||
urb->status == -ECONNRESET ||
urb->status == -ESHUTDOWN)) {
dbg("%s - nonzero write bulk status received: %d",
__FUNCTION__, urb->status);
}

/* 釋放已分配的緩沖區 */
usb_buffer_free(urb->dev, urb->transfer_buffer_length,
urb->transfer_buffer, urb->transfer_dma);
}
有時候USB驅動程序只是要發送或者接收一些簡單的數據,驅動程序也可以不用urb來進行數據的傳輸,這是里涉及到兩個簡單的介面函數:usb_bulk_msg和usb_control_msg ,在這個USB框架程序里讀操作就是這樣的一個應用:
/* 進行阻塞的批量讀以從設備獲取數據 */
retval = usb_bulk_msg(dev->udev,
usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr),
dev->bulk_in_buffer,
min(dev->bulk_in_size, count),
&count, HZ*10);

/*如果讀成功,復制到用戶空間 */
if (!retval) {
if (_to_user(buffer, dev->bulk_in_buffer, count))
retval = -EFAULT;
else
retval = count;
}
usb_bulk_msg介面函數的定義如下:
int usb_bulk_msg(struct usb_device *usb_dev,unsigned int pipe,
void *data,int len,int *actual_length,int timeout);
其參數為:
struct usb_device *usb_dev:指向批量消息所發送的目標USB設備指針。
unsigned int pipe:批量消息所發送目標USB設備的特定端點,此值是調用usb_sndbulkpipe或者usb_rcvbulkpipe來創建的。
void *data:如果是一個OUT端點,它是指向即將發送到設備的數據的指針。如果是IN端點,它是指向從設備讀取的數據應該存放的位置的指針。
int len:data參數所指緩沖區的大小。
int *actual_length:指向保存實際傳輸位元組數的位置的指針,至於是傳輸到設備還是從設備接收取決於端點的方向。
int timeout:以Jiffies為單位的等待的超時時間,如果該值為0,該函數一直等待消息的結束。
如果該介面函數調用成功,返回值為0,否則返回一個負的錯誤值。
usb_control_msg介面函數定義如下:
int usb_control_msg(struct usb_device *dev,unsigned int pipe,__u8 request,__u8requesttype,__u16 value,__u16 index,void *data,__u16 size,int timeout)
除了允許驅動程序發送和接收USB控制消息之外,usb_control_msg函數的運作和usb_bulk_msg函數類似,其參數和usb_bulk_msg的參數有幾個重要區別:
struct usb_device *dev:指向控制消息所發送的目標USB設備的指針。
unsigned int pipe:控制消息所發送的目標USB設備的特定端點,該值是調用usb_sndctrlpipe或usb_rcvctrlpipe來創建的。
__u8 request:控制消息的USB請求值。
__u8 requesttype:控制消息的USB請求類型值。
__u16 value:控制消息的USB消息值。
__u16 index:控制消息的USB消息索引值。
void *data:如果是一個OUT端點,它是指身即將發送到設備的數據的指針。如果是一個IN端點,它是指向從設備讀取的數據應該存放的位置的指針。
__u16 size:data參數所指緩沖區的大小。
int timeout:以Jiffies為單位的應該等待的超時時間,如果為0,該函數將一直等待消息結束。
如果該介面函數調用成功,返回傳輸到設備或者從設備讀取的位元組數;如果不成功它返回一個負的錯誤值。
這兩個介面函數都不能在一個中斷上下文中或者持有自旋鎖的情況下調用,同樣,該函數也不能被任何其它函數取消,使用時要謹慎。
我們要給未知的USB設備寫驅動程序,只需要把這個框架程序稍做修改就可以用了,前面我們已經說過要修改製造商和產品的ID號,把0xfff0這兩個值改為未知USB的ID號。
#define USB_SKEL_VENDOR_ID 0xfff0
#define USB_SKEL_PRODUCT_ID 0xfff0
還 有就是在探測函數中把需要探測的介面端點類型寫好,在這個框架程序中只探測了批量(USB_ENDPOINT_XFER_BULK)IN和OUT端點,可 以在此處使用掩碼(USB_ENDPOINT_XFERTYPE_MASK)讓其探測其它的端點類型,驅動程序會對USB設備的每一個介面進行一次探測, 當探測成功後,驅動程序就被綁定到這個介面上。再有就是urb的初始化問題,如果你只寫簡單的USB驅動,這塊不用多加考慮,框架程序里的東西已經夠用 了,這里我們簡單介紹三個初始化urb的輔助函數:
usb_fill_int_urb :它的函數原型是這樣的:
void usb_fill_int_urb(struct urb *urb,struct usb_device *dev,
unsigned int pipe,void *transfer_buff,
int buffer_length,usb_complete_t complete,
void *context,int interval);
這個函數用來正確的初始化即將被發送到USB設備的中斷端點的urb。
usb_fill_bulk_urb :它的函數原型是這樣的:
void usb_fill_bulk_urb(struct urb *urb,struct usb_device *dev,
unsigned int pipe,void *transfer_buffer,
int buffer_length,usb_complete_t complete)
這個函數是用來正確的初始化批量urb端點的。
usb_fill_control_urb :它的函數原型是這樣的:
void usb_fill_control_urb(struct urb *urb,struct usb_device *dev,unsigned int pipe,unsigned char *setup_packet,void *transfer_buffer,int buffer_length,usb_complete_t complete,void *context);
這個函數是用來正確初始化控制urb端點的。
還有一個初始化等時urb的,它現在還沒有初始化函數,所以它們在被提交到USB核心前,必須在驅動程序中手工地進行初始化,可以參考內核源代碼樹下的/usr/src/~/drivers/usb/media下的konicawc.c文件。

F. linux虛擬機安裝問題求助

是你的主機的硬碟滿了,而不是 vb 的虛擬硬碟滿了。
vb 的虛擬硬碟是變動大小的。
-------------------------------
FAT32 的話,你的虛擬機硬碟選擇的是單文件方式,還是拆分文件?
FAT32 不支持大文件,這里必須選擇拆分。不然你的虛擬機的硬碟選擇再大也沒用。

G. linux中怎麼使用gdb調試進程有dettach

在2.5.60版Linux內核及以後,GDB對使用fork/vfork創建子進程的程序提供了follow-fork-mode選項來支持多進程調試。 follow-fork-mode的用法為: set follow-fork-mode [parentchild] parent: fork之後繼續調試父進程,子進程不受影響。 child: fork之後調試子進程,父進程不受影響。 因此如果需要調試子進程,在啟動gdb後: (gdb) set follow-fork-mode child並在子進程代碼設置斷點。 此外還有detach-on-fork參數,指示GDB在fork之後是否斷開(detach)某個進程的調試,或者都交由GDB控制: set detach-on-fork [onoff] on: 斷開調試follow-fork-mode指定的進程。 off: gdb將控制父進程和子進程。follow-fork-mode指定的進程將被調試,另一個進程置於暫停(suspended)狀態。 注意,最好使用GDB 6.6或以上版本,如果你使用的是GDB6.4,就只有follow-fork-mode模式。 follow-fork-mode/detach-on-fork的使用還是比較簡單的,但由於其系統內核/gdb版本限制,我們只能在符合要求的系統上才能使用。而且,由於follow-fork-mode的調試必然是從父進程開始的,對於fork多次,以至於出現孫進程或曾孫進程的系統,例如上圖3進程系統,調試起來並不方便。 Attach子進程 眾所周知,GDB有附著(attach)到正在運行的進程的功能,即attach <pid>命令。因此我們可以利用該命令attach到子進程然後進行調試。 例如我們要調試某個進程RIM_Oracle_Agent.9i,首先得到該進程的pid [root@tivf09 tianq]# ps -efgrep RIM_Oracle_Agent.9i nobody 6722 6721 0 05:57 ? 00:00:00 RIM_Oracle_Agent.9i root 7541 27816 0 06:10 pts/3 00:00:00 grep -i rim_oracle_agent.9i通過pstree可以看到,這是一個三進程系統,oserv是RIM_Oracle_prog的父進程,RIM_Oracle_prog又是RIM_Oracle_Agent.9i的父進程。 [root@tivf09 root]# pstree -H 6722通過 pstree 察看進程 啟動GDB,attach到該進程 用 GDB 連接進程 現在就可以調試了。一個新的問題是,子進程一直在運行,attach上去後都不知道運行到哪裡了。有沒有辦法解決呢? 一個辦法是,在要調試的子進程初始代碼中,比如main函數開始處,加入一段特殊代碼,使子進程在某個條件成立時便循環睡眠等待,attach到進程後在該代碼段後設上斷點,再把成立的條件取消,使代碼可以繼續執行下去。 至於這段代碼所採用的條件,看你的偏好了。比如我們可以檢查一個指定的環境變數的值,或者檢查一個特定的文件存不存在。以文件為例,其形式可以如下: void debug_wait(char *tag_file) { while(1) { if (tag_file存在) 睡眠一段時間; else break; } }當attach到進程後,在該段代碼之後設上斷點,再把該文件刪除就OK了。當然你也可以採用其他的條件或形式,只要這個條件可以設置/檢測即可。 Attach進程方法還是很方便的,它能夠應付各種各樣復雜的進程系統,比如孫子/曾孫進程,比如守護進程(daemon process),唯一需要的就是加入一小段代碼。 GDB wrapper 很多時候,父進程 fork 出子進程,子進程會緊接著調用 exec族函數來執行新的代碼。對於這種情況,我們也可以使用gdb wrapper 方法。它的優點是不用添加額外代碼。 其基本原理是以gdb調用待執行代碼作為一個新的整體來被exec函數執行,使得待執行代碼始終處於gdb的控制中,這樣我們自然能夠調試該子進程代碼。 還是上面那個例子,RIM_Oracle_prog fork出子進程後將緊接著執行RIM_Oracle_Agent.9i的二進制代碼文件。我們將該文件重命名為RIM_Oracle_Agent.9i.binary,並新建一個名為RIM_Oracle_Agent.9i的shell腳本文件,其內容如下: [root@tivf09 bin]# mv RIM_Oracle_Agent.9i RIM_Oracle_Agent.9i.binary [root@tivf09 bin]# cat RIM_Oracle_Agent.9i #!/bin/sh gdb RIM_Oracle_Agent.binary當fork的子進程執行名為RIM_Oracle_Agent.9i的文件時,gdb會被首先啟動,使得要調試的代碼處於gdb控制之下。

H. 什麼樣的程序讓linux負載變大

在linux系統裡面,常見的有兩個地方可以看到當前系統的最近平均負載,top命令和uptime,如果執行一下uptime命令的話,可以看到有一個load average,表示最近1分鍾,5分鍾,15分鍾的系統負載。
# uptime
23:31:04 up 5 days, 10:20, 1 user, load average: 0.00, 0.01, 0.05
一般單核的CPU的話,負載到1證明系統已經運行比較滿了,多核的話,有幾個核就能到幾。
但是,有沒有仔細想過,這個負載值究竟可以有多高?
我們先用一個程序做下實驗

等這個程序運行一會,再執行uptime看下負載
# uptime
23:44:53 up 5 days, 10:33, 2 users, load average: 16383.13, 14111.52, 7705.88
看到沒,這個程序竟然把load神奇的刷到了16000這個級別,真是厲害,這個一下子似乎打破了對系統負載的認識。
原理是這樣的,通過調用vfork產生指定數量的D狀態的進程,從而提高負載。看看系統文檔,是這樣說的
vfork() differs from fork(2) in that the calling thread is suspended until the child terminates (either normally, by calling _exit(2), or abnormally, after delivery of a fatal signal), or it makes a call to execve(2). Untilthat point, the child shares all memory with its parent, including the stack.
vfork 的子進程只要不 execve 或者退出,父進程就一直掛著(在D狀態)。這里就是讓最後一個子進程用 scanf 等輸入。
但是這個就是極限了嗎?
程序員在這種事情上是不會停止追求的,下來再看一個終極版本的程序

執行一下
# stap -g loadavg.stp $(((1
看下效果
# uptime
23:48:19 up 5 days, 10:37, 2 users, load average: 9007199254740991.00, 14987.03, 9007199254740991.00
我天,這是要爆表了,終極load,系統要炸了嗎?
不過,你知道其中的原理嗎,vfork相當於還是利用了系統計算load的原理,通過增加D狀態進程影響計算,這個終極版,則是直接修改計算過程中用到的參數,讓系統算出一個極大值來,沒有什麼能夠超越這個了。

閱讀全文

與linuxsuspended相關的資料

熱點內容
win10plsql 瀏覽:819
香港電影開頭一個女的在床上自慰 瀏覽:512
win10cdromsys下載 瀏覽:30
桌面程序hibernate 瀏覽:14
如何建蔬菜網站 瀏覽:579
android網路通信聊天 瀏覽:1
電影頭上裹著布還有紐扣 瀏覽:246
iphone6nfc充電 瀏覽:422
鐵銹戰爭的文件夾是哪個 瀏覽:184
大數據業務描述 瀏覽:162
古惑仔粵語版歌詞 瀏覽:897
韓國劇情片網站 瀏覽:759
自學滅火器編程該如何入手 瀏覽:817
網站ip地址怎麼防禦 瀏覽:572
大數據自動化部署 瀏覽:368
自動編程軟體有哪些有什麼特色 瀏覽:140
韓國污片網站 瀏覽:758
主角要收集各種女子 瀏覽:463
《哈佛女孩》電影 瀏覽:422

友情鏈接