grViz製作過程如下:
-----
推薦專欄另外兩篇相關文章: linux C函數調用棧 以及 linux文件樹
老白Walt:[R] 如何用樹展示linux C函數調用棧 - collapsibleTree
老白Walt:[R] 展示linux文件樹 - collapsibleTree
R源碼如下:
library(DiagrammeR) library(dplyr)
add_box <- function(df, t, pref, suff) { df$desc[df$type %in% t] %<>% paste0(pref, ., suff) return(df) }
fc <- getcsv(d:/linux-master/schedule_flow.csv) %>% add_box(c(d, r), (, )) %>% add_box(c(s), [, ]) %>% add_box(c(c), {, }) %>% mutate(seq = paste0(id, desc))
fc$seq = sub(^(\d..+)\((.*)\), \1<br/>arg: \2, fc$seq, perl = T)
data <- select(fc, id, eid = tid) %>% na.omit() %>% mutate(sep = -->) %>% bind_rows(select(fc, id, eid = fid) %>% na.omit %>% mutate(sep = -.->))
mmd <- sapply(select(data, id, eid), qdapTools::lookup, select(fc, id, seq)) %>% as.data.frame() %>% bind_cols(select(data, sep)) %>% {paste( graph TB, with(., paste0(id, sep, eid, collapse = )), sep =
)}
mermaid(mmd)
mmd是字元串,它的格式是:
[節點因子][左形狀][內容][右形狀]-->[節點因子][左形狀][內容][右形狀]
形狀:
貼出可以直接執行的代碼(生成的代碼沒啥意思就不帖了):
grViz(" digraph { graph [overlap = true] edge [color = slategray, arrowhead = vee, penwidth = 5] node [shape = oval, fontsize = 32, fontcolor = darkslategray, color = darkorange, width = 3, height = 2, penwidth = 3] 1. int ret; 2. struct device_driver *other node [shape = rectangle, fontsize = 32, fontcolor = darkslategray, color = steelblue, width = 4, height = 2, penwidth = 3] 4. pr_err(`Driver %s was unable to register with bus_type %s because the bus was not initialized. `, drv->name, drv->bus->name); 5. return -EINVAL; 7. printk(KERN_WARNING `Driver %s needs updating - please use ` `bus_type methods `, drv->name); 8. other = driver_find(drv->name, drv->bus); 10. printk(KERN_ERR `Error: Driver %s is already registered, ` `aborting... `, drv->name); 11. return -EBUSY; 12. ret = bus_add_driver(drv); 14. return ret; 15. ret = driver_add_groups(drv, drv->groups); 17. bus_remove_driver(drv); 18. return ret; 19. kobject_uevent(&drv->p->kobj, KOBJ_ADD); 20. return ret node [shape = diamond, fontsize = 32, fontcolor = darkslategray, color = mediumseagreen, width = 4, height = 3, penwidth = 4] 3. !drv->bus->p; 6. (drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown); 9. other; 13. ret; 16. ret node [shape = point, fillcolor = slategray, color = gray, width = 1, height = 1] 21. 1. int ret->2. struct device_driver *other; 2. struct device_driver *other->3. !drv->bus->p; 3. !drv->bus->p->4. pr_err(`Driver %s was unable to register with bus_type %s because the bus was not initialized. `, drv->name, drv->bus->name)[color = forestgreen]; 4. pr_err(`Driver %s was unable to register with bus_type %s because the bus was not initialized. `, drv->name, drv->bus->name)->5. return -EINVAL; 5. return -EINVAL->21. ; 6. (drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)->7. printk(KERN_WARNING `Driver %s needs updating - please use ` `bus_type methods `, drv->name)[color = forestgreen]; 7. printk(KERN_WARNING `Driver %s needs updating - please use ` `bus_type methods `, drv->name)->8. other = driver_find(drv->name, drv->bus); 8. other = driver_find(drv->name, drv->bus)->9. other; 9. other->10. printk(KERN_ERR `Error: Driver %s is already registered, ` `aborting... `, drv->name)[color = forestgreen]; 10. printk(KERN_ERR `Error: Driver %s is already registered, ` `aborting... `, drv->name)->11. return -EBUSY; 11. return -EBUSY->21. ; 12. ret = bus_add_driver(drv)->13. ret; 13. ret->14. return ret[color = forestgreen]; 14. return ret->21. ; 15. ret = driver_add_groups(drv, drv->groups)->16. ret; 16. ret->17. bus_remove_driver(drv)[color = forestgreen]; 17. bus_remove_driver(drv)->18. return ret; 18. return ret->21. ; 19. kobject_uevent(&drv->p->kobj, KOBJ_ADD)->20. return ret; 20. return ret->21. ; 3. !drv->bus->p->6. (drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)[color = tomato]; 6. (drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)->8. other = driver_find(drv->name, drv->bus)[color = tomato]; 9. other->12. ret = bus_add_driver(drv)[color = tomato]; 13. ret->15. ret = driver_add_groups(drv, drv->groups)[color = tomato]; 16. ret->19. kobject_uevent(&drv->p->kobj, KOBJ_ADD)[color = tomato] } ", width = 1900, height = 1470)
說白了就是按照一定的格式將node(節點)和edge(連線)在字元串中列出來, 有興趣深入了解的可以移步下面examples:
就如視頻所示,製作linux中任意一個C函數(遵循linux coding style)的流程圖5分鐘之內就能搞定
先理一下設計思路:
難點:
最後附上本例使用的R包:
DiagrammeR?rich-iannone.github.iorich-iannone/DiagrammeR?github.com
本專欄只生產乾貨,喜歡請關註:
TAG:Linux內核 | C/C | 數據可視化 |