Pages

Monday, December 18, 2017

All about volatile variable in C

What is volatile keyword in C?
volatile is a data type qualifier in C.

Role of volatile variable in signal handler?
When a variable is declared as volatile, the C compiler does not optimize the code where this variable involves.

It also means that someone might externally change the value of this variable over time, hence do not cache the value of this variable.

In case of interrupt handlers or signal handlers where the counter is dependent is on the incoming data, this counter variables value changes due to external factors like arrival of new data on the port. Hence even though the program did not modified the data, the value of this counter variable changed. Such variable should be declared as volatile variable, so that the C compiler does not optimize the usage of this variable and hence does not pick up the value from the cache.

Logical & and addition

What is going to be the output of this code?

  1 #include
  2 int main(void)
  3 {
  4     int a=10, b=12;
  5     int c;
  6     c = a&b + 65;
  7     printf("c=%d\n", c);

  8}

This code looks simple enough. Guess??

Friday, December 15, 2017

const behavior of a variable in C Programming Language

When you intend to not change the value of a variable you declare it as a const in C language.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
int c1()
{
  int *a;
  const int b;

  a=&amp;b;

  printf("*a=%d, b=%d\n",*a, b);
  
  *a = *a + 1;
  //b = b + 1; 

  printf("*a=%d, b=%d\n", *a, b);

//return ;
}

main()
{       
        printf("C=%d\n", c1());
}




If you execute 
  b = b + 1:
then the compiler complains:
c1.c:12:5: error: cannot assign to variable 'b' with const-qualified type 'const int'
  b = b + 1; 
  ~ ^
c1.c:5:13: note: variable 'b' declared const here
  const int b;
  ~~~~~~~~~~^

That's what is expected.
But if we declare a pointer variable and that points to the const variable, and you increment the "value" of what the pointer variable is pointing to, then the compiler does not complain. Why?

Using only 
  *a = *a + 1;
actually increments the value of b because it's same as *a.



Let's change the program slightly:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
int c1()
{
  int *a;
  const int b;

  a=&b;

  printf("*a=%d, b=%d\n",*a, b);
  
  *a = *a + 1;
  //b = b + 1; 

  printf("*a=%d, b=%d\n", *a, b);

//return ;
}

main()
{       
        printf("C=%d\n", c1());

}

This time the compiler gives an error.

s1.c:11:6: error: read-only variable is not assignable
  *a = *a + 1;
  ~~ ^

So, the rational is if you use the const identifier, then you can't update it's value.



Static variable behavior

How the static variable behaves?

#include
//int s1();
int s1()
{
  static int s;
  return s++;
}

main()
{
  int i=1;
  while (i<=2)
  {      
    i++;
    printf("S=%d\n", s1());
  }

}



Simple program. But here's the trick.
s is a static variable. 

    return s++;
the post increment is done as if:
    
    return s;
    s = s + 1;

So, when the first time s1() prints, it prints the value of s = 0, s being a static variable it's initialized to 0. But the first time s1() returns before it's being incremented. The next statement of course executes, and s is incremented. Since it's a static variable, it's not in the call stack, hence it's got incremented after the s1() function returns, but before the function actually exits.

As per Wikipedia:
When the program (executable or library) is loaded into memorystatic variables are stored in the data segment of the program's address space (if initialized), or the BSS segment (if uninitialized), and are stored in corresponding sections of object files prior to loading.

As per this 1995 Linux Journal article: http://www.linuxjournal.com/article/1059
Executable code is always placed in a section known as .text; all data variables initialized by the user are placed in a section known as .data; and uninitialized data is placed in a section known as .bss.

Hence the static variable actually increments.

Wednesday, August 12, 2015

Let's run a c program by hand

Let’s compile a C program by hand. The aim is to compile the a.c program.

$cat a.h
#define AA 100
$cat a.c
#include “a.h”
main()
{
            printf(“%d apples”, AA);
            exit(19);
}
$

So, this is the program we really wanted to compile.
$gcc a.c –o a.exe
$./a.exe
100 apples$
$

To know what’s happening behind the scene, do this:
[kongkon@cadbury ~]$ gcc -v a.c
Reading specs from /usr/lib/gcc/i386-redhat-linux/3.4.3/specs
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux
Thread model: posix
gcc version 3.4.3 20050227 (Red Hat 3.4.3-22.1)
 /usr/libexec/gcc/i386-redhat-linux/3.4.3/cc1 -quiet -v a.c -quiet -dumpbase a.c  -auxbase a -version -o /tmp/ccfWiYm9.s
ignoring nonexistent directory "/usr/lib/gcc/i386-redhat-linux/3.4.3/../../../../i386-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/local/include
 /usr/lib/gcc/i386-redhat-linux/3.4.3/include
 /usr/include
End of search list.
GNU C version 3.4.3 20050227 (Red Hat 3.4.3-22.1) (i386-redhat-linux)
compiled by GNU C version 3.4.3 20050227 (Red Hat 3.4.3-22.1).
GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128313
 as -V -Qy -o /tmp/ccyJwUTb.o /tmp/ccfWiYm9.s
GNU assembler version 2.15.92.0.2 (i386-redhat-linux) using BFD version 2.15.92.0.2 20040927
 /usr/libexec/gcc/i386-redhat-linux/3.4.3/collect2 --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crt1.o /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crti.o /usr/lib/gcc/i386-redhat-linux/3.4.3/crtbegin.o -L/usr/lib/gcc/i386-redhat-linux/3.4.3 -L/usr/lib/gcc                                                                /i386-redhat-linux/3.4.3 -L/usr/lib/gcc/i386-redhat-linux/3.4.3/../../.. /tmp/cc yJwUTb.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s                                                                              --no-as-needed /usr/lib/gcc/i386-redhat-linux/3.4.3/crtend.o /usr/lib/gcc/i386-redhat-linux/3.4.3/../../../crtn.o
[kongkon@cadbury ~]$
Understood? It’s really hard to understand. Let me explain a little, and then things will look simpler. The –v switch to gcc explains what gcc has done with the compilation process. Now, first of all what is gcc? gcc is the compiler like everyone would say. Yes, it is the compiler. Actually it is a wrapper, which calls different programs to compile the C program: if you look at the –v output more closely you will see that, gcc calls "cpp", the C preprocessor first, then "cc1", the C compiler, and then "as", the assembler. As an output we get the object file, the same what we get by running “gcc –c a.c”. Here we take help of the linker, "ld", to link a.o with our library for printf, since we have not written code of printf() of our own. We need to link our a.o with libc.so for printf code, as specified by -lc. This outputs a.exe, out executable. Run this, and enjoy 100 apples.

Let’s do every thing by hand. Let’s call all of them one by one. First the C preprocessor, cpp.
[kongkon@cadbury ~]$ cpp a.c
# 1 "a.c"
# 1 ""
# 1 ""
# 1 "a.c"
# 1 "a.h" 1
# 2 "a.c" 2
main()
{
 printf("%d apples",100);
exit(19);
}
[kongkon@cadbury ~]$
cpp by default dumps the output in the console, redirect it to a file, call it a.i.
[kongkon@cadbury ~]$ cpp a.c -o a.i
[kongkon@cadbury ~]$
[kongkon@cadbury ~]$ ls a.*
a.c  a.h  a.i
[kongkon@cadbury ~]$

Next is the C compiler, cc1.
[kongkon@cadbury ~]$ cc1 a.i
-bash: cc1: command not found
[kongkon@cadbury ~]$
Oops! Bash did not find  cc1, he does not know where is cc1. Take the help of gcc itself to find where cc1 is. Do this:
[kongkon@cadbury ~]$ gcc -print-prog-name=cc1
/usr/libexec/gcc/i386-redhat-linux/3.4.3/cc1
[kongkon@cadbury ~]$
Next, compile a.i, not a.c.
[kongkon@cadbury ~]$ /usr/libexec/gcc/i386-redhat-linux/3.4.3/cc1 a.i
 main

Execution times (seconds)
 parser                :   0.01 (100%) usr   0.00 ( 0%) sys   0.00 ( 0%) wall
 TOTAL                 :   0.01             0.00             0.01
[kongkon@cadbury ~]$
[kongkon@cadbury ~]$ ls a.*
a.c  a.h  a.i  a.s
This produces a.s.
Now, call the assembler, to create the object file, a.o.
[kongkon@cadbury ~]$ as a.s -o a.o
So, we have the object file here, a.o.
[kongkon@cadbury ~]$ ls a.*
a.c  a.h  a.i  a.o  a.s
[kongkon@cadbury ~]$
Now, call the linker program, ld.
[kongkon@cadbury ~]$ ld -o a.exe a.o -e main -lc -dynamic-linker /lib/ld-linux.so.2
[kongkon@cadbury ~]$ ls a.*
a.c  a.exe  a.h  a.i  a.o  a.s
[kongkon@cadbury ~]$
So, here we have the executable binary a.exe.
Run this and you will see the same output as we did in our first step.
[kongkon@cadbury ~]$ ./a.exe
100 apples[kongkon@cadbury ~]$
 Check whether the program exited successfully.
kongkon@cadbury ~]$ echo $?
19 
[kongkon@cadbury ~]$


So, we have successfully compiler a C program. Happy programming.

The thread ends here.

Wednesday, December 03, 2014

rpm spec file magic

In Unix flavored Operating Systems various software packages are packaged along with the source file in the form of an rpm package. The rpm package contains the source rpm and the binary rpm, along with optional other dependent tools rpm packages that is needed for the main binary rpm to work. In earlier days it was achieved in the form of an tarball, which contains the configure script. The configure scripts calls the Makefile to build the final binary package that's finally ready to installed on that platform.


Here I plan to discuss some of the tricks I have learned in the rpm spec file.
The spec file contains various sections:
a) %description
b) %prep
c) %build
d) %install
e) %files
f) %package  ## This is optional section
g) %clean
h) %changelog

Some of these sections are self explanatory, like the %description, %clean and %changelog section. The most interesting things happen in the %build, %install and %files section.
In the %build and %install section you can write anything that you can write in a bash script, they understand the bash syntax and executes them.
The %files section however does not understand the bash scripting language, and only understand the rpm macros.
If you want to include addition packages in the same package.spec.in file, then the %package section comes handy, and you include a %package section for each additional rpm package you intend to produce.


The basic structure goes like this:
# This is a comment
Name:          my-package
Version:        1.0
Release:        %RPM_RELTAG%
Summary:     my package update release
Source:         %RPM_SOURCE%
License:        License info
Vendor:         The source code belong to
Packager:      The repackaging is done by
Group:          System Environment/Libraries
Requires:       my-package-tools
BuildRequires:  coreutils                  ##dependent packages needed to build this package

%description
This provides the my package which is very important for everyone.


%define debug_package %{nil}
## This is how you define a local variable (called prefix)
%define prefix  /lib/firmware/important/


%define MY_FILE_LIST %{expand:%( \
FW="" \
FW+=" a.bin" \    ## a file
FW+=" b.bin" \     ## b file
FW+=" c.bin"        ##c file
##FW+=" c1.bin" \   ##c1 file
FW+=" d.bin"        ##d file
FW+=" e.bin"    ##e file
FW+=" f.bin"    ## f file
echo $FW \
)}

%global flist() %{expand:%( \
files="%*" \
if [ -n "%{?1}" ] ; then \
for pkg in $files  \
do \
  echo "%%{prefix}/$pkg" \
done \
fi \
)}

%prep
%setup -n src



## The % build section is also common between the base rpm package and additional (tools) rpm package

%build
RM=rm
MD5SUM=/usr/bin/md5sum 
## md5sum is part of coreutils, hence it's mentioned in the BuildRequires

cd fw/
${RM} -fr checksum.txt

for FW in %{MY_FILE_LIST}; do \
        echo ${FW}; \
        ${MD5SUM} ${FW} >> checksum.txt; \
done

%install
install -d ${RPM_BUILD_ROOT}%{prefix}/
cd fw/



## This will install all the a.bin, b.bin etc files into the right place, no need list one by one
for FW in %{MY_FILE_LIST}; do \
        install ${FW} ${RPM_BUILD_ROOT}%{prefix};
done
install checksum.txt ${RPM_BUILD_ROOT}%{prefix}

## The tools rpm that this spec file produces installs the my_special_tool as part of it, and
## the % install section is common for both the base package and the addition (tools) package
# Install Tools files
install -d ${RPM_BUILD_ROOT}%{prefix}
cd ../tools
install -m 0755 -D my_special_tool ${RPM_BUILD_ROOT}%{prefix}

%files
%defattr(0664,root,root)
## This is the magic
% flist %MY_FILE_LIST
## Otherwise you have to install each individual file separately like
#% {prefix}/a.bin
#% {prefix}/b.bin
#etc

## Now comes information about the additional package
##
## Tools package
##

%package tools
Summary:        %{name} deployment tools
Group:          System Environment/Base
Requires:       special-tools >= 1.4-5

%description tools
This package provides the special deployment tool for the my software.

%files tools
%defattr(-,root,root,-)
%attr(700,root,root) %{prefix}/my_special_tool
%doc %{_mandir}/man8/my_special_tool.8.gz

%clean
rm -rf ${RPM_BUILD_ROOT}

%changelog
* Wed Dec 03 2014 Kongkon Jyoti Dutta
        - ABC-123 Releasing my special tool to the world


Tuesday, June 10, 2014

How to update the drive firmware in Linux



echo "Using firmware file $fwfile for upgrading $product on device $x…"

The process to download in Solid State Drive and Hard Disk Drive is a little different. In case of SDD we can burn the firmware in one command, but in case of HDD we need to write in a loop since there is a limitation of 0x80000 bytes on VFS module system call.



           if [ "$rev" != "$target_fw_ver" ]; then
               echo "Upgrading $disk_type firmware to version $target_fw_ver on $x i.e.$sg_dev..."
               if  [ "$disk_type" = "ssd" ]; then
                   sg_write_buffer --in=${fwfile} --mode=5 --id=0 $sg_dev
                   if [ $? -ne 0 ]; then
                       echo "Failed to upgrade SSD firmware on $x i.e.$sg_dev to version $target_fw_ver!" >&2
                       exit 1
                   fi
               else
                   # hdd firmware upgrade
                   bytes=`ls -l $fwfile | awk '{ print $5; }'`
                   start=0
       #length = 0x80000 Bytes
                   length=524288
                   while [ $start -lt $bytes ]; do
                       if let 'start+length>bytes'; then
                           let 'length=bytes-start'
                       fi
                       sg_write_buffer --in=$fwfile --skip=$start --offset=$start --length=$length --mode=0x7 --id=0 $sg_dev
                       if [ $? -ne 0 ]; then
                           echo "Failed to upgrade HDD firmware $x i.e.$sg_dev to version $target_fw_ver!" >&2
                           exit 1
                       fi
                       let start+=length
                   done
               fi

Wednesday, October 31, 2012

Let's see what you installed

Google+
To install packages in Linux:
Packages can be installed using yum, or rpm. Each one has it's own internal database that list what is already installed into the system.

To install a package using yum:
#yum install

To install a package using rpm:
#rpm -ivh
#rpm -Uvh

To check what is already installed:

To check what is yum installed:
#yum list | grep


To check what is rpm installed:
#rpm -qa | grep



HTH
--kongkon